Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Questions and comments specific to a particular plugin should go here.
Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Thu Jan 26, 2017 3:29 pm

Oh, btw, is it possible to generate events with this plug-in, like it is with the Onkyo plug-in (which I use for another amp in the house)? That creates events in EG when I turn it on or do other stuff, so I can use those events to update the webpage with the status of the amp when I turn it off or on (or mute it, or change the input) from the app or with an IR remote.

Edit: I do of course know that I can run an eternal check of the power status for the two zones I use, for instance every five seconds. But it would just be nice if I didn't have to.

Dragon470
Experienced User
Posts: 202
Joined: Thu Feb 10, 2011 2:16 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Dragon470 » Thu Jan 26, 2017 11:29 pm

Yamaha receivers do not push out any data unless asked. It has to be polled to do events. I had made a script to do checks every 5 seconds (for everything), and found out it would freeze and lock my older rx-v671. An update years ago did stop the locking but I don't have a use for it anymore and don't have the script. BirdApi and I agreed to not implement polling as there are too many variables that would have to be kept track of across different models.

I think if you wanted just a few it would be easier to implement your own polling in a separate script having its own thread as to not take up the main eventghost programming thread.

Even the direct website of the receiver does a polling every 5 seconds. It also does an poll when you push a button.

Sorry if that is not really what you wanted to hear.

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Fri Jan 27, 2017 7:33 am

Well, it was was I expected. :mrgreen: So I'm not disappointed. My problem is that I have no idea how to do threading. Do you by any chance have a tip on that? A simple script would be like this:

Code: Select all

#Create the variables I use for comparing (this will be a table in the finished script,
#but that's not a problem for me).
eg.globals.Amp1 = 'Standby'

Sone1Status = eg.plugins.YamahaRX.GetInfo('Power', 'Main Zone') #Checking the status of the amp
print(Sone1Status)#For debugging
if Sone1Status == eg.globals.Amp1:#Compare the current status of the amp to the stored status
    print('No change, no action necessary.')

else:
    eg.globals.eg.globals.Amp1 = Sone1Status #Update the stored status with the changed value
    print('There is a change, so it is necessary to update the system.') #The actual update is a separate function script and probably not necessary for this question
So I would like to get that into a separate thread, but how?

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Fri Jan 27, 2017 10:16 am

Oh, and the timer isn't as easy as I thought either. I guess it has to be threaded too, right? In LUA I can make repeating timers easily, but not in Python... :oops:

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Fri Jan 27, 2017 10:45 am

What I do for now is the egg timer in SchedulGhost (here assuming that the value of the global variables are already set, so they are commented out):

Code: Select all

eg.plugins.SchedulGhost.StartEggTimer((u'00:00:10', u'SchedulGhost', u'YamahaSjekk', u'', u'', (191, 191, 255), (64, 0, 128), u'0;-56;0;0;0;400;0;0;0;0;0;0;0;0;MS Shell Dlg 2', (10, 10), u'EggTimer'))

#Create the variables I use for comparing (this will be a table in the finished script,
#but that's not a problem for me).
#eg.globals.Amp1 = 'Standby'

Sone1Status = eg.plugins.YamahaRX.GetInfo('Power', 'Main Zone') #Checking the status of the amp
print(Sone1Status)#For debugging
if Sone1Status == eg.globals.Amp1:#Compare the current status of the amp to the stored status
    print('No change, no action necessary.')

else:
    eg.globals.eg.globals.Amp1 = Sone1Status #Update the stored status with the changed value
    print('There is a change, so it is necessary to update the system.') #This update is a separate function script, not necessary for this info

#eg.globals.Amp2 = 'Standby'

Sone2Status = eg.plugins.YamahaRX.GetInfo('Power', 'Zone 2') #Checking the status of the amp
print(Sone2Status)#For debugging
if Sone2Status == eg.globals.Amp2:#Compare the current status of the amp to the stored status
    print('No change, no action necessary.')

else:
    eg.globals.eg.globals.Amp2 = Sone2Status #Update the stored status with the changed value
    print('There is a change, so it is necessary to update the system.') #This update is a separate function script, not necessary for this info
This works, and ten seconds doesn't tax anything. But of course it would be nice to thread each of the polls in it's own thread and then maybe even run them constantly, so every time an answer comes back, it makes them check again. It shouldn't be a problem for the amp since I can use the web page and the app at the same time without any problems.

Dragon470
Experienced User
Posts: 202
Joined: Thu Feb 10, 2011 2:16 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Dragon470 » Fri Jan 27, 2017 1:40 pm

Here is a very crude example using the built in Get Info action.

Code: Select all

import threading
import time
#eg.TriggerEvent(suffix, payload,prefix)
#could call this from the start of eg.
#should delay as to make sure the plugin was started.

def worker(element, zone, PreviousVar="", kill=False):
    if PreviousVar == "":
        #setup PreviousVar with actual data from receiver
        PreviousVar = Yamahavariable = eg.plugins.YamahaRX.GetInfo(element, zone)
    while kill == False:
        TempVar = Yamahavariable = eg.plugins.YamahaRX.GetInfo(element, zone)
        if TempVar != PreviousVar:
            eg.TriggerEvent(zone + " - " + element, TempVar, "YamahaRX")
            PreviousVar = TempVar
        time.sleep(3) #time in seconds

threads = []  #stores all the thread info for later managment
t = threading.Thread(target=worker, args=("Volume Level","Main Zone"))
threads.append(t)
t.start()
# main (eventghost) thread exits now while others are working
#keep in mind these are not currently killable (they will run indefinately)
#   This can be changed but I don't have the time in a short example

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Fri Jan 27, 2017 1:50 pm

Thanks a lot! I will have a look at it tonight. So basically the only way to kill them would be to restart EG, then? But if I start it twice by accident, will that be a problem, or does a new start kill the previous running set?

Dragon470
Experienced User
Posts: 202
Joined: Thu Feb 10, 2011 2:16 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Dragon470 » Fri Jan 27, 2017 10:32 pm

I just got a chance to finish the scripts. This is a little closer and in some ways easier than what I had years ago. First script allows you to add as many "objects" you want to monitor. The second script kills them all.

Code: Select all

import threading
import time
#eg.TriggerEvent(suffix, payload,prefix)
#could call this from the start of eg.
#should delay as to make sure the plugin was started.

#class worker(threading.Thread):

def worker(element, zone, kill=False):
    #setup PreviousVar with actual data from receiver
    PreviousVar = Yamahavariable = eg.plugins.YamahaRX.GetInfo(element, zone)
    while True:
        TempVar = Yamahavariable = eg.plugins.YamahaRX.GetInfo(element, zone)
        if TempVar != PreviousVar:
            eg.TriggerEvent(zone + " - " + element, TempVar, "YamahaRX")
            PreviousVar = TempVar
        time.sleep(3) #time in seconds
        if kill():
            break
    print "Exiting " + zone + " - " + element

eg.globals.Yamaha_Stop_Threads = False
eg.globals.YamahaThreads = []  #stores all the thread info for later managment
objects = []
objects.append(["Volume Level","Main Zone"])
objects.append(["Power","Main Zone"])
objects.append(["Mute","Main Zone"])
for i in objects:
    t = threading.Thread(target=worker, args=(i[0],i[1], lambda: eg.globals.Yamaha_Stop_Threads))
    eg.globals.YamahaThreads.append(t)
    t.start()
    
# main (eventghost) thread exits now while others are working
# threads can be terminated via command eg.globals.YamahaThreads[x].join()
# this is done in a seperate script in my example

Code: Select all

import threading

eg.globals.Yamaha_Stop_Threads = True
for t in eg.globals.YamahaThreads:
    t.join()

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Sat Jan 28, 2017 10:26 am

Brilliant, thanks a lot! I fiddled a bit yesterday, but this is really good to work with! :mrgreen: I'll let you know if I run into any snags. Or if I don't, and it works perfectly.

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Sun Jan 29, 2017 2:06 pm

Yep, it works perfectly, thanks! Just the thing I need! I have set it to follow input, power and mute status. :mrgreen:

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Sun Jan 29, 2017 4:13 pm

So next question is: Would it be possible to add two levels to the info? I would like to know the level of my subs (one set of 15" as sub 1 on the amp and one set of 12" subs as sub 2). It's nice to know, because I have a need for totally different levels when watching reguar tv, watching movies and listening to music.I have this code that I can use:

Code: Select all

speakers = eg.plugins.YamahaRX.GetInfo('PreOut Levels', 'System')
for x in speakers:
    if x[0] == "Subwoofer_1":
        eg.globals.Subwoofer15 = x[1]
        eg.globals.Subwoofer15 = eg.globals.Subwoofer15+0      #sets for future use so it doesn't have to poll the receiver again
But it would be nice to avoid he extra lines of code and just being able to poll directly.Or maybe it doesn't take up any more ressources running this script every three seconds, instead of you adding a direct view of it? Btw It's very possible that you helped me with that code a year or two back. :mrgreen:

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Sun Jan 29, 2017 4:29 pm

Oops... Sorry, this is when the check code fount out it wanted to throw an error:

Code: Select all

17:28:10   Unable to communicate with Yamaha Receiver. The connection timed out.
17:28:10   Exception in thread Thread-39982:
17:28:10   Traceback (most recent call last):
17:28:10     File "threading.pyc", line 532, in __bootstrap_inner
17:28:10     File "threading.pyc", line 484, in run
17:28:10     File "126", line 14, in worker
17:28:10     File "C:\Program Files (x86)\EventGhost\plugins\yamaha-network-receivers-master\client.py", line 558, in __call__
17:28:10       return get_status_string(self.plugin, object,zone)
17:28:10     File "C:\Program Files (x86)\EventGhost\plugins\yamaha-network-receivers-master\yamaha_xml.py", line 134, in get_status_string
17:28:10       xmldoc = minidom.parseString(xml)
17:28:10     File "xml\dom\minidom.pyc", line 1928, in parseString
17:28:10     File "xml\dom\expatbuilder.pyc", line 940, in parseString
17:28:10     File "xml\dom\expatbuilder.pyc", line 223, in parseString
17:28:10   TypeError: Parse() argument 1 must be string or read-only buffer, not None
17:28:10   
As far as I can see this happens in the plug-in script, not in my user script, right?

Dragon470
Experienced User
Posts: 202
Joined: Thu Feb 10, 2011 2:16 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Dragon470 » Sun Jan 29, 2017 8:47 pm

So the error occurred in the plugin when the script was calling it. The plugin did not get a proper response from the receiver. It either timed out (which I thought the plugin would not throw the error if that happened), or got back a garbage response and could not parse it. If you keep getting this error lengthen the sleep timeout in the plugin and see if it continues to happen.


As far as getting the levels of the speakers:

I just tried to get a value of a specific speaker and it failed to work.
The one in Get Info is the branch that is callable to the receiver and it always gives all speakers. Sometimes the receiver will not let you call further out on the branch. However, the added code to get the specific speaker level should be measured in milliseconds. I don't think it is hurting anything.

therealbiglou
Experienced User
Posts: 105
Joined: Sat May 19, 2012 4:33 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by therealbiglou » Mon Jan 30, 2017 4:35 am

For a while now, randomly the plugin will lose connection with my Receiver. The receiver is set to a static IP and the plugin is set to the same. Sometimes shutting down the reciever and/or EG will fix it. Other times it doesn't. It almost always will eventually fix itself. When I try to run a macro with the plugin, it will cause long pauses in EG while it tries to find a connection with the receiver. During this time, any other network dependent plugin will work flawlessly. Any tips?

Mastiff
Experienced User
Posts: 754
Joined: Thu May 03, 2012 10:43 am

Re: Yamaha RX-Vxxx (or similar) Ethernet Plugin!

Post by Mastiff » Mon Jan 30, 2017 7:36 am

Dragon470, I changed the sleep timeout of the threaded script to 5 seconds instead of 3 because almost at once I started using it because I had quite a few of those when I was connected to the amp with the app or the web page (which is when I need the script the most so the automation system can see changes that are made), and with 5 seconds it doesn't happen often. I still get them every now and then, but not often. Or do you mean a sleep timeout in the plugin-it self? There are a few timeout lines, like this one:

Code: Select all

def __start__(self, ip_address="", port=80, ip_auto_detect=True, auto_detect_model="ANY", auto_detect_timeout=1.0, default_timeout=3.0):
Perhaps it is possible to change the ANY to the specific receiver? Or perhaps the auto detect only happens when EG starts up or the plug-in is activated?

As for the script I will implement that and see if it does change anything, but then I doubt it.

Thanks! :mrgreen:

Post Reply