Control Denon AVR via XBMC/evenghost/other
#31
Hi @ll,

In my opinion it would be great if we had a new addon extension point for the remote control of the connected AV receiver. So it would be possible to implement protocols of other companies (Onkyo, Maranz, ...) and use the corresponding addon.

Furthermore, it would be great if we override the volume control of kodi (xbmc) and display the current volume of the AV receiver in kodi.

The idea with this addon types came, because it annoys me that I always need two remotes for kodi. One for the control of kodi and the other to control my Denon.

At the moment I think the best is to use Pyhton script as addons, so the addons could be easily and quickly developed. Also the integration of the various protocols (HTTP, Telnet, ...) that are needed to control the AV receivers would be more easier to integrat.

At the moment I'm thinking of the following functions:
  • Automatic source change, was started when kodi
  • Volume control of the AV-Receiver () by kodi
  • Volume display of the AV receiver in kodi
  • On / off the AV receiver during the start and end of Kodi
  • Save AV-Receiver Settings in profile and set the corresponding profile for different media

What do you think of the idea?
Do you have more ideas, what features this addons should support?
Reply
#32
Hi,
I'm new here.
I have a Denon AVR x-1000 and I would like to know more about the http protocol (comands) to control my AVR.
The examples above are working perfectly! But I cannot find out for example how to change the STEREO mode...
Can somebody help me?

THX

Chucrute
Reply
#33
Looks like this same concept can work for Pioneer AVR's. Here's a blog page that shows the telnet commands for them:

http://raymondjulin.com/2012/07/15/remot...er-telnet/

I've just started playing with Kodi on a Rasbperry Pi, just got the Flirc gadget. I have built an IR command translator with Basic Stamp, allowing me to use a Tivo Remote Control to control everything in my Home TV Setup. Looking forward to doing that again, but better, with the Pi!
Reply
#34
Problem solved.
Reply
#35
Only for all of the People who also need to control their Denon / Marantz AV-Receiver via Network:

I found yesterday in another (german) Forum an Eventghost Plugin which is working with the telnet protocol to control the AV-receiver:
http://www.dvbviewer.tv/forum/topic/4822.../?p=377054

For me it is working flawlessly.

On the Denon Website their are documentation for all receivers with the commands inside.
(For Marantz has no documentation about this, but you can also use the denon docs, The Receivers have the same firmware. For example a Marantz SR7008 is a pimped Denon x4000)
so I can now switch Audyssey LFC on/off with my mute button Big Grin

I'm using a Xbox One Remote with Flirc on an Windows Machine with Kodi 15.1
Eventghost switches the receiver on at Systemstart and switches to the correct Input.
(The Receiver has to be switched on before Kodi starts in my Case. If this is not the case, Kodi switch to a wrong screen resolution.)
Also the receiver is switched off on system shutdown and of course I can control the Volume with my remote Wink

I wrote this here, that anybody who is searching for something similar has a reference.
(I hope this helps someone who has the same problem as I had Nerd
and sorry about my poor english)

To be Complete here is the Code from the plugin (it references the GPL, so I think it is ok to post it here):

(If you don't want to register to the other Forum to download the plugin you can Copy & Paste the Code here into a "__init__.py" File for Eventghost and copy this file into the plugin Directory of Eventghost)
Code:
# This file is a plugin for EventGhost.
#
#
# EventGhost is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# EventGhost is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EventGhost; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import eg

eg.RegisterPlugin(
    name = "Denon Network Control",
    version = "0.1",
    author = "Nuts (based on Pioneer_AV_NET by ThomasBott) ",
    description = (
        "Sends events to a Denon Receiver through TCP/IP."
    ),
    kind = "external",
    icon = (
        "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/"
        "AAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH1gIQFgQOuRVmrAAAAVRJREFUOMud"
        "kjFLw2AQhp+kMQ7+jJpCF+ni1lFEwUXq5g+wgiCCgoNUrG5Oltb2DygGYwUXwbmbg+Li"
        "IhSHhobaora2MZTGoQb5aBLFd/u4u/fuufskApQ92DWAFOEqKSHB1OzMHJoW8w1aloVR"
        "1tNhBmhajPnlQ9/Yzdk2AKEGkiQBkExOAS4wfFcqDwwGg6FBGGv++IiF5DiOZPHcnKDb"
        "+6T9YQs5iscajSd8p2jUqhhlnZfXYfeIMgaA67o/CNF4gsW1C1RVJHKcPlfFJQCaZt23"
        "geKxqqpCYnpSYL2/feIbleuTrZErjCwxEpGpNzp0ew7tjshaKOb8BsgIBnePdXAlz05g"
        "XV1ZEyplWaZQzGUVL8lx+qhv7yM78NRqtYJ30KhVucynAq8AoJ+fBhqUjLKe/uXPZzI7"
        "e/tBBumN9U1s2/at9FiBQANM0+S/UsL4/qIvHUp+5VOP+PAAAAAASUVORK5CYII="
    ),
    createMacrosOnAdd = True,
)


import socket
import select
import re
from time import sleep
from threading import Event, Thread

ACTIONS = (

(eg.ActionGroup, 'GroupMainControls', 'Denon Actions', None, (

    ('PowerOn', 'Power On', None, 'PWON'),
    ('PowerOff', 'Power Standby', None, 'PWSTANDBY'),

    ('MasterUp', 'Master Volume Up', None, 'MVUP'),
    ('MasterDown', 'Master Volume Down', None, 'MVDOWN'),

    ('MuteOn', 'Mute On', None, 'MUON'),
    ('MuteOff', 'Mute Off', None, 'MUOFF'),

    ('MainZoneOn', 'Main Zone On', None, 'ZMON'),
    ('MainZoneOff', 'Main Zone Off', None, 'ZMOFF'),

    ('Z2On', 'Zone 2 On', None, 'Z2ON'),
    ('Z2Off', 'Zone 2 Off', None, 'Z2OFF'),
    ('Z2Source', 'Zone 2 Source', None, 'Z2SOURCE'),
    ('Z2VolUp', 'Zone 2 Volume Up', None, 'Z2UP'),
    ('Z2VolDown', 'Zone 2 Volume Down', None, 'Z2DOWN'),
    ('Z2MuteOn', 'Zone 2 Mute On', None, 'Z2MUON'),
    ('Z2MuteOff', 'Zone 2 Mute Off', None, 'Z2MUOFF'),

    ('DelayUp', 'Audio Delay Increasse', None, 'PSDELAY UP'),
    ('DelayDown', 'Audio Delay Decrease', None, 'PSDELAY DOWN'),

    ('SMDirect','Surround Mode DIRECT', None, 'MSDIRECT'),
    ('SMPureDirect','Surround Mode PURE DIRECT', None, 'MSPURE DIRECT'),
    ('SMStereo','Surround Mode STEREO', None, 'MSSTEREO'),
    ('SMDolbyPLIIx','Surround Mode DOLBY PL2X', None, 'MSDOLBY PL2X'),


    ('ModeMusic', 'Programm Mode Music', None, 'PSMODE:MUSIC'),
    ('ModeCinema', 'Programm Mode Cinema', None, 'PSMODE:CINEMA'),
    ('ModeGame', 'Programm Mode Game', None, 'PSMODE:GAME'),
)),

)




class NetworkSender(eg.PluginBase):

    def __init__(self):

        self.AddActionsFromList(ACTIONS, Send_Action)
        self.AddAction(Send_Custom_Action)


    def __start__(self, ip, port):
        self.ip = ip
        self.port = port
        self.Connect()
        self.stopThreadEvent = Event()
        thread = Thread(
            target=self.Receive,
            args=(self.stopThreadEvent, )
        )
        thread.start()

    def __stop__(self):
        self.stopThreadEvent.set()
        self.socket.close()

    def Receive(self, stopThreadEvent):
        while not stopThreadEvent.isSet():
            try:
                ready = select.select([self.socket], [], [])
                # the first element of the returned list is a list of readable sockets
                if ready[0]:
                    # 1024 bytes should be enough for every received event
                    response = self.socket.recv(1024)
                    # splits the received string in substrings for every event
                    splitter="\r\n"
                    responseArray=response.split(splitter)
                    responseArrayLen=len(responseArray)-1
                    for i in range(0, responseArrayLen, 1):
                        response=responseArray[i]
                        if response!="":
                            if response[:3]=="VOL":
                                response1=response[:3]
                                response2=response[3:]
                                self.TriggerEvent(response1, payload=response2)
                            elif response[:3]=="FRF":
                                response1=response[:3]
                                response2=response[3:]
                                self.TriggerEvent(response1, payload=response2)
                            elif response[:2]=="FL":
                                # data displayed on the receiver
                                response1=response[:2]
                                response2=response[2:]
                                response3=""
                                while response2!="":
                                    # converts hex to ascii
                                    character=int(response2[:2], 16)
                                    if character==5:
                                        character="|)"
                                    elif character==6:
                                        character="(|"
                                    elif character==8:
                                        character="II"
                                    else:
                                        character=chr(character)
                                    response3=response3+character
                                    response2=response2[2:len(response2)]
                                response4=unicode(re.sub(" ", " ", response3[1:]), 'latin-1', 'replace')
                                #displays the data as an event with payload:
                                #self.TriggerEvent(response1, payload=response4)
                                #saves the data to the variale "AVDisplay":
                                eg.globals.AVDisplay=response4
                            elif len(response)<=10:
                                self.TriggerEvent(response)
                            else:
                                print response
                            sleep(0.01)
            except Exception as e:
                print "Denon Network Control:",e
                if "10054" in e:
                    print "trying to reconnect"
                    self.plugin.Connect()
                stopThreadEvent.wait(3.0)
        self.TriggerEvent("ThreadStopped!")


    def Configure(self, ip="127.0.0.1", port=23):

        panel = eg.ConfigPanel()
        ipCtrl = panel.TextCtrl(ip)
        portCtrl = panel.SpinIntCtrl(port, max=65535)

        st1 = panel.StaticText("IP")
        st2 = panel.StaticText("Port")
        eg.EqualizeWidths((st1, st2))
        tcpBox = panel.BoxedGroup(
            "TCP/IP Settings",
            (st1, ipCtrl),
            (st2, portCtrl),
        )

        panel.sizer.Add(tcpBox, 0, wx.EXPAND)

        while panel.Affirmed():
            panel.SetResult(
                ipCtrl.GetValue(),
                portCtrl.GetValue(),
            )

    def Connect(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.settimeout(1.0)
        self.socket = s

        ip = self.ip
        port = self.port
        try:
            s.connect((ip, port))
        except Exception as e:
            print "Failed to connect to " + ip + ":" + str(port), e
        else:
            print "Connected to " + ip + ":" + str(port)

class Send_Action(eg.ActionBase):
    def __call__(self):
        line = str(self.value)+'\r'

        try:
            self.plugin.socket.sendall(line)
            sleep(0.1)
        except socket.error, msg:
            print "Error sending command, retrying", msg
            self.plugin.Connect()
            try:
                self.plugin.socket.sendall(line)
            except socket.error, msg:
                print "Error sending command", msg




class Send_Custom_Action(eg.ActionBase):

    def __call__(self, myAction=""):

        line = str(myAction)+'\r'
        #eg.Print(line)
        try:
            self.plugin.socket.sendall(line)
            sleep(0.1)
        except socket.error, msg:
            print "Error sending command, retrying", msg
            self.plugin.Connect()
            try:
                self.plugin.socket.sendall(line)
            except socket.error, msg:
                print "Error sending command", msg



    def Configure( self, myAction ="" ):
        panel = eg.ConfigPanel()
        actionCtrl = panel.TextCtrl(myAction)
        panel.AddLine("Action: ", actionCtrl)

        while panel.Affirmed():
            panel.SetResult(actionCtrl.GetValue())
Reply
#36
(2015-01-10, 12:42)Chucrute Wrote: I have a Denon AVR x-1000 and I would like to know more about the http protocol (comands) to control my AVR.
The examples above are working perfectly! But I cannot find out for example how to change the STEREO mode...
Can somebody help me?

On the Denon Website you can find pdf files with all supported commands inside. I think it should be also possible to change the Stereo mode with an command.
Reply
#37
guys, i need your help!

I've modified the XBMC addon from Jeroen to suite my needs.

Thought i'll add a cool automatic shutdown function.... well seems like my python skills are not enough for that Sad

I've modified the default.py like this:
Code:
import xbmc
import telnetlib
import time
import xbmcaddon
import json
startedplay = 0
__addon__ = xbmcaddon.Addon(id='script.jeroenvds.denonremote')

def turnOnDenon():
    tn = telnetlib.Telnet(__addon__.getSetting("denonip"))
    tn.write("PWON\r")
    time.sleep(3)
    tn.write("QS3\r")
    #print tn.read_eager()
    tn.close()
    
def turnOffDenon():
    var = 30
    while var > 0:
        if startedplay == 1:
            return
        else:
            time.sleep(10)
            var = var -1
    
    tn = telnetlib.Telnet(__addon__.getSetting("denonip"))
    tn.write("QS1\r")
    time.sleep(3)
    tn.write("PWSTANDBY\r")
    #print tn.read_eager()
    tn.close()
    
    
    
    
    
def changeVolumeDenon(volume):
    if volume > 98:
        volume = 98
    elif volume < 0:
        volume = 0
        
    tn = telnetlib.Telnet(__addon__.getSetting("denonip"))    
    tn.write("MV"+"{0:02d}".format(volume)+"\r")
    tn.close()
    

class DenonWatcher(xbmc.Monitor):
    def __init__(self, *args, **kwargs):
        xbmc.Monitor.__init__(self)
                
    def onNotification(self, sender, method, data):
        global startedplay
        if method == "Player.OnPlay":
            startedplay = 1
            turnOnDenon()
        elif method == "Player.OnStop":
            startedplay = 0
            turnOffDenon()
        elif method == "Player.OnVolumeChanged":
            dataDecoded = json.loads(data)
            changeVolumeDenon(dataDecoded['volume'])
            
        
        

class PlayerWhichStartsDenon(xbmc.Player):
    def onPlayBackStarted(self):
        tn = telnetlib.Telnet(HOST)
        tn.write("PWON\r")
        time.sleep(1)
        tn.write("SIMPLAY\r")
        #print tn.read_eager()
        tn.close()
        
#player = PlayerWhichStartsDenon()
monitor = DenonWatcher()

while not xbmc.abortRequested:
    xbmc.sleep(60000)

My issue is with the "def turnOffDenon():" This should sleep 30 times 10 seconds before shutting down the Denon.
Sadly it only sleeps for 10 seconds, aka 1 tick and then shuts the denon Down.

Another issue is that when i click "Stop" and "play" instantly it will still shutdown and then start the Denon.


Does anyone here have a good idea which method i could use to check if the Denon is still playing something as the script seems to pause the "OnNotification" during sleep.
Is there any way to start a new "wait for on notification" during the sleep mode while waiting for shut down?




greetings
a Python n00b.
Reply

Logout Mark Read Team Forum Stats Members Help
Control Denon AVR via XBMC/evenghost/other2