Page 2 of 3

Re: Plugin Denon AVR-X2100W

Posted: Tuesday 21 February 2017 13:26
by Dnpwwo
@l00pz,

@oohlaf reported the -273.1499 bug in Domoticz (not the plugin) and suggested a fix, a pull request is waiting to be merged.

Can you give the next beta version a go and I will have another look at the plugin if it still doesn't work.

Re: Plugin Denon AVR-X2100W

Posted: Tuesday 21 February 2017 16:22
by gielie
I tried the new beta but still no luck with the volume.

Code: Select all

2017-02-21 16:21:24.073 User: Machiel initiated a switch command (301/Denon AVR X-2100 - Main Volume/Set Level)
2017-02-21 16:21:24.079 (Denon AVR X-2100) Calling message handler 'onCommand'.
2017-02-21 16:21:24.080 (Denon AVR X-2100) onCommand called for Unit 3: Parameter 'Set Level', Level: -273.1499938964844
2017-02-21 16:21:24.080 (Denon AVR X-2100) Sending data: 'MV-273.1499938964844 '.
And neither with the input selector

Code: Select all

2017-02-21 16:22:36.185 User: Machiel initiated a switch command (300/Denon AVR X-2100 - Main Zone/Set Level)
2017-02-21 16:22:36.222 (Denon AVR X-2100) Calling message handler 'onCommand'.
2017-02-21 16:22:36.223 (Denon AVR X-2100) onCommand called for Unit 2: Parameter 'Set Level', Level: -273.1499938964844
2017-02-21 16:22:36.223 Error: (Denon AVR X-2100) 'onCommand' failed 'KeyError'.
2017-02-21 16:22:36.223 Error: (Denon AVR X-2100) ----> Line 213 in /home/pi/domoticz/plugins/Denon/plugin.py, function onCommand 

Another error in the script

Code: Select all

2017-02-21 16:37:17.202 User: Machiel initiated a switch command (300/Denon AVR X-2100 - Main Zone/Set Level)
2017-02-21 16:37:17.247 (Denon AVR X-2100) Calling message handler 'onCommand'.
2017-02-21 16:37:17.247 (Denon AVR X-2100) onCommand called for Unit 2: Parameter 'Set Level', Level: -273.1499938964844
2017-02-21 16:37:17.248 Error: (Denon AVR X-2100) 'onCommand' failed 'KeyError'.
2017-02-21 16:37:17.248 Error: (Denon AVR X-2100) ----> Line 213 in /home/pi/domoticz/plugins/Denon/plugin.py, function onCommand
2017-02-21 16:37:18.450 (Denon AVR X-2100) Calling message handler 'onHeartbeat'.
2017-02-21 16:37:18.451 (Denon AVR X-2100) onHeartbeat: lastMessage PW, Sending 'ZM'.

Re: Plugin Denon AVR-X2100W

Posted: Tuesday 21 February 2017 20:18
by l00pz
@gielie The latest Pull Request hasn't been merged yet, so we need to wait for this.

Re: Plugin Denon AVR-X2100W

Posted: Tuesday 21 February 2017 20:48
by gielie
Oh haha, ill wait.

Re: Plugin Denon AVR-X2100W

Posted: Friday 24 February 2017 18:19
by l00pz
@Dnwwwo the Plugin seems to be working now in the latest commit! Thanks :D

Re: Plugin Denon AVR-X2100W

Posted: Saturday 25 February 2017 10:52
by gielie
I updated to the latest beta and its working, yeah, tanks.

There is only 1 inconvenience, when I turn on the main device, zone 2 turns on. And when I turn off the main device, zone 2 won't turn off. I have to manually turn off zone 2.

I created a script when main zone is off turn zone 2 off.

Is there a better solution?

Re: Plugin Denon AVR-X2100W

Posted: Monday 27 February 2017 13:27
by raymond
l00pz wrote:@Dnwwwo the Plugin seems to be working now in the latest commit! Thanks :D
I can confirm the same, briliant !

Any plans to add Surround Modes into a Selector switch too? I'm not up to speed on python, but it would seems possible to do this same way as the Source Input selector.

Have this plugin running on a Marantz NR1602 without flaws now. Previously had a lot of LUA and xml parsing done to get this same result.
Great work ! Save me a bunch.

Ray

Re: Plugin Denon AVR-X2100W

Posted: Monday 27 February 2017 14:17
by Dnpwwo
@gielie,

Although my amp has 3 zones I only use 1. I just added the other code in there to show what could be done. I've had a look at the code and there is nothing obvious so you will need to post a log with debug turned on to help me spot the problem.

I thought I was treating the zones as separate so the amp shouldn't turn off until all zones are turned off (which seems to line up with what you are seeing) but if the power is off and a command is recieved, I send Power On which I thought would restore it to the last state. This works for one zone but maybe not multi-zone.

Perhaps I should try sending the specific zone on command not Power On to see if that works better. The manual is rubbish unfortunately so I'll need to play a bit.

@raymond,

Didn't realise this would work on Marantz as well. Happy days !

Is that set per zone or just at the amp level? There is no reason it wouldn't work

Re: Plugin Denon AVR-X2100W

Posted: Monday 27 February 2017 14:52
by raymond
Yes works on Marantz also :D . The protocol and Parameter list is exactly the same, though SOURCE names are different, but that is also true for different Denon models I believe.

The Selector Switch for SOURCES and the SI command work the same way on my Marantz NR1602, same goes for MV, PW and ZM/Z2 commands.

Selecting the surround mode would work like the SOURCE INPUT you already have implemented. Creating another Selector Switch like the SOURCE INPUT but with different names (DOLBY, DTS, STEREO, AUTO etc.) would do the trick, along with the MS command sent instead of SI (Page 12 and 29 of the protocol.pdf shared earlier)

I'm happy as is, but if you're looking to implement more features, this would be on my list. I've seen folks getting into the PS command which handles all equalizer stuff, but that wouldn't have my initial interest.

Cheers,

Ray

Re: Plugin Denon AVR-X2100W

Posted: Tuesday 28 February 2017 23:00
by G3rard
I am using the script for my Marantz NR1604 and it all seems to work.
I only get the error messages in the log like: Unknown message '@P' ignored. See the detailled log below.

I am using the latest beta v3.6807 and updated the Sources field with the right sources from my Marantz (copied the names from the web gui of the Marantz).

Any ideas how to fix this? Or is this something specific for the Marantz?

Code: Select all

2017-02-28 22:54:12.908 (Marantz) onMessage called with Data: '@PWR:1'
2017-02-28 22:54:12.908 Error: (Marantz) Unknown message '@P' ignored.
2017-02-28 22:54:22.324 (Marantz) Calling message handler 'onHeartbeat'.
2017-02-28 22:54:22.324 (Marantz) onHeartbeat: lastMessage PW, Sending 'ZM'.
2017-02-28 22:54:22.324 (Marantz) Sending data: 'ZM? '.
2017-02-28 22:54:22.375 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:22.375 (Marantz) onMessage called with Data: 'ZMOFF'
2017-02-28 22:54:22.375 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:22.375 (Marantz) onMessage called with Data: '@PWR:1'
2017-02-28 22:54:22.375 Error: (Marantz) Unknown message '@P' ignored.
2017-02-28 22:54:32.359 (Marantz) Calling message handler 'onHeartbeat'.
2017-02-28 22:54:32.359 (Marantz) onHeartbeat: lastMessage ZM, Sending 'SI'.
2017-02-28 22:54:32.359 (Marantz) Sending data: 'SI? '.
2017-02-28 22:54:32.427 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:32.427 (Marantz) onMessage called with Data: 'SITV'
2017-02-28 22:54:32.427 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:32.427 (Marantz) onMessage called with Data: '@SRC:11'
2017-02-28 22:54:32.427 Error: (Marantz) Unknown message '@S' ignored.
2017-02-28 22:54:32.427 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:32.427 (Marantz) onMessage called with Data: 'PSMDAX OFF'
2017-02-28 22:54:32.477 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:32.477 (Marantz) onMessage called with Data: '@MDA:1'
2017-02-28 22:54:32.477 Error: (Marantz) Unknown message '@M' ignored.
2017-02-28 22:54:32.527 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:32.527 (Marantz) onMessage called with Data: 'SVOFF'
2017-02-28 22:54:42.344 (Marantz) Calling message handler 'onHeartbeat'.
2017-02-28 22:54:42.344 (Marantz) onHeartbeat: lastMessage SI, Sending 'MV'.
2017-02-28 22:54:42.344 (Marantz) Sending data: 'MV? '.
2017-02-28 22:54:42.394 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:42.394 (Marantz) onMessage called with Data: 'MV56'
2017-02-28 22:54:42.394 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:42.394 (Marantz) onMessage called with Data: '@VOL:-240'
2017-02-28 22:54:42.394 Error: (Marantz) Unknown message '@V' ignored.
2017-02-28 22:54:42.462 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:42.462 (Marantz) onMessage called with Data: 'MVMAX 97'
2017-02-28 22:54:42.462 (Marantz) Unknown: Action MV, Detail 'MAX 97' ignored.
2017-02-28 22:54:52.329 (Marantz) Calling message handler 'onHeartbeat'.
2017-02-28 22:54:52.329 (Marantz) onHeartbeat: lastMessage MV, Sending 'MU'.
2017-02-28 22:54:52.329 (Marantz) Sending data: 'MU? '.
2017-02-28 22:54:52.379 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:52.379 (Marantz) onMessage called with Data: 'MUOFF'
2017-02-28 22:54:52.379 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:54:52.379 (Marantz) onMessage called with Data: '@AMT:1'
2017-02-28 22:54:52.379 Error: (Marantz) Unknown message '@A' ignored.
2017-02-28 22:55:02.361 (Marantz) Calling message handler 'onHeartbeat'.
2017-02-28 22:55:02.361 (Marantz) onHeartbeat: lastMessage MU, Sending 'PW'.
2017-02-28 22:55:02.361 (Marantz) Sending data: 'PW? '.
2017-02-28 22:55:02.428 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:55:02.428 (Marantz) onMessage called with Data: 'PWSTANDBY'
2017-02-28 22:55:02.428 (Marantz) Calling message handler 'onMessage'.
2017-02-28 22:55:02.428 (Marantz) onMessage called with Data: '@PWR:1'
2017-02-28 22:55:02.428 Error: (Marantz) Unknown message '@P' ignored.

Re: Plugin Denon AVR-X2100W

Posted: Wednesday 01 March 2017 9:14
by raymond
G3rard wrote:I am using the script for my Marantz NR1604 and it all seems to work.
I only get the error messages in the log like: Unknown message '@P' ignored. See the detailled log below.

I am using the latest beta v3.6807 and updated the Sources field with the right sources from my Marantz (copied the names from the web gui of the Marantz).

Any ideas how to fix this? Or is this something specific for the Marantz?
I have the same thing on my NR1602 indeed. I do not know if I did something wrong or if it's just the Marantz. Everything else works flawless.

Ray

Re: Plugin Denon AVR-X2100W

Posted: Saturday 04 March 2017 7:45
by Dnpwwo
@raymond & @G3rard,

The plugin will be fine because this is just the warning when it sees something unexpected and isn't in 'ignoreMessages' on line 57.

Given that it appears more amps than I expected can use this maybe 'ignoreMessages' should be a parameter. I'm a little tied up on something else at the moment and can look at it in a few days maybe.

Re: Plugin Denon AVR-X2100W

Posted: Sunday 05 March 2017 17:18
by raymond
I don't mind the message, it clogs up the log a bit, but all works fine!

Ray

Re: Plugin Denon AVR-X2100W

Posted: Thursday 09 March 2017 0:33
by G3rard
@Dnpwwo, I have added @P|@M|@S|@V|@A to the ignoreMessages in the plugin and then it's working fine :D

Also tried to add that field to the parameters by adding

Code: Select all

<param field="Ignore" label="Ignore Messages" width="550px" required="true" default="|SS|SV|SD|MS|PS|CV|@P|@M|@S|@V|@A|"/>
and on line 57

Code: Select all

ignoreMessages = str(Parameters["Ignore"])
but that gives a NameError in the log.

Code: Select all

2017-03-09 00:27:48.637 Error: (Denon4306) failed to load 'plugin.py', Python Path used was '/home/gerard/domoticz/plugins/Denon/:/usr/lib/python3.4/:/usr/lib/python3.4/plat-x86_64-linux-gnu:/usr/lib/python3.4/lib-dynload'.
2017-03-09 00:27:48.637 Error: (Marantz) Module Import failed, exception: 'NameError'
Can you point me in the right direction (sorry no Python knowledge yet...).

Re: Plugin Denon AVR-X2100W

Posted: Saturday 11 March 2017 1:17
by Dnpwwo
@G3rard,

The field name needs to be one that Domoticz knows about. Have a look at http://www.domoticz.com/wiki/Developing ... Definition for the list of valid values.

I'm working on another version and was going to do a simpler fix which was to make it just log the message when debugging was turned on (which is probably when it is more useful than the current one)

Re: Plugin Denon AVR-X2100W

Posted: Saturday 11 March 2017 22:22
by G3rard
Thanks, didn't read that part of the wiki indeed...
However after changing the name to Mode4 or Mode5 I still get the same error :?
I will just wait for your new version.

Re: Plugin Denon AVR-X2100W

Posted: Saturday 11 March 2017 22:59
by Dnpwwo
@G3rard,

You need to do the assignment inside onStart (or any other callback). When Python imports a file it also executes it so everything outside a function is evaluated (standard behaviour I can't stop it) but the Domoticz values have not been set up at that point so the Parameters dictionary does not exist (hence the NameError)

Just initialise it to "" on line 57 and then update it in a callback.

Re: Plugin Denon AVR-X2100W

Posted: Saturday 11 March 2017 23:44
by G3rard
@Dnpwwo,

Thanks, I added the ignoreMessages to onStart and then it works.

However when I click on Update in the Hardware tab I get the following error.

Code: Select all

2017-03-11 23:42:59.671 Error: PluginList: Error 'Error document empty.' at line 0 column 0 in XML ''.
2017-03-11 23:43:02.699 (Marantz) Exiting work loop...
2017-03-11 23:43:02.700 Error: Plugin: Async Read Exception: 125, Operation canceled
2017-03-11 23:43:02.701 (Marantz) Denon device has disconnected.
2017-03-11 23:43:02.783 (Marantz) Stopped.
2017-03-11 23:43:02.845 (Marantz) Initialized version 2.2.0, author 'dnpwwo'
2017-03-11 23:43:02.896 (Marantz) Connected successfully to: 192.168.1.138:23
This is my plugin.py code.
Spoiler: show

Code: Select all

#
#       Denon AVR 4306 Plugin
#
#       Author:     Dnpwwo, 2016
#
#   Mode3 ("Sources") needs to have '|' delimited names of sources that the Denon knows about.  The Selector can be changed afterwards to any  text and the plugin will still map to the actual Denon name.
#
"""
<plugin key="Denon4306" version="2.2.0" name="Denon AVR 4306 Amplifier" author="dnpwwo" wikilink="" externallink="http://www.denon.co.uk/uk">
    <params>
        <param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
        <param field="Port" label="Port" width="30px" required="true" default="23"/>
        <param field="Mode1" label="Zone Count" width="50px" required="true">
            <options>
                <option label="1" value="1"/>
                <option label="2" value="2"/>
                <option label="3" value="3"  default="true" />
            </options>
        </param>
        <param field="Mode2" label="Startup Delay" width="50px" required="true">
            <options>
                <option label="2" value="2"/>
                <option label="3" value="3"/>
                <option label="4" value="4" default="true" />
                <option label="5" value="5"/>
                <option label="6" value="6"/>
                <option label="7" value="7"/>
                <option label="10" value="10"/>
            </options>
        </param>
        <param field="Mode3" label="Sources" width="550px" required="true" default="Off|DVD|VDP|TV|CD|DBS|Tuner|Phono|VCR-1|VCR-2|V.Aux|CDR/Tape|AuxNet|AuxIPod"/>
        <param field="Mode4" label="Ignore Messages" width="550px" required="true" default="|SS|SV|SD|MS|PS|CV|@P|@M|@S|@V|@A|"/>
        <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

isConnected = False
nextConnect = 3
oustandingPings = 0

# Device Status - When off set device values to negative
powerOn = False
mainSource = 0
mainVolume1 = 0
zone2Source = 0
zone2Volume = 0
zone3Source = 0
zone3Volume = 0

# ignoreMessages = "|SS|SV|SD|MS|PS|CV|@P|@M|@S|@V|@A|"
ignoreMessages = ""
selectorMap = {}
pollingDict = {"PW":"ZM?\r", "ZM":"SI?\r", "SI":"MV?\r", "MV":"MU?\r", "MU":"Z2?\r", "Z2":"Z3?\r", "Z3":"PW?\r" }
lastMessage = ""

def onStart():
    global mainSource, mainVolume1, zone2Source, zone2Volume, zone3Source, zone3Volume, ignoreMessages

    ignoreMessages = str(Parameters["Mode4"])
    
    if Parameters["Mode6"] == "Debug":
        Domoticz.Debugging(1)
    LevelActions = '|'*Parameters["Mode3"].count('|')
    # if Zone 3 required make sure at least themain device exists, otherwise suppress polling for it
    if (Parameters["Mode1"] > "2"):
        if (6 not in Devices):
            Domoticz.Device(Name="Zone 3", Unit=6, TypeName="Selector Switch", Switchtype=18, Image=5, \
                            Options="LevelActions:"+stringToBase64(LevelActions)+";LevelNames:"+stringToBase64(Parameters["Mode3"])+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ==").Create()
            if (7 not in Devices): Domoticz.Device(Name="Volume 3", Unit=7, Type=244, Subtype=73, Switchtype=7,  Image=8).Create()
            Domoticz.Log("Created Zone 3 device(s) because zone requested in hardware setup but device not found.")
        else:
            zone3Source = Devices[6].nValue
            if (7 in Devices): zone3Volume = int(Devices[7].sValue)
    else:
        pollingDict.pop("Z3")
        pollingDict["Z2"] = "PW?\r"
    
    # if Zone 2 required make sure at least themain device exists, otherwise suppress polling for it
    if (Parameters["Mode1"] > "1"):
        if (4 not in Devices):
            Domoticz.Device(Name="Zone 2", Unit=4, TypeName="Selector Switch", Switchtype=18, Image=5, \
                            Options="LevelActions:"+stringToBase64(LevelActions)+";LevelNames:"+stringToBase64(Parameters["Mode3"])+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ==").Create()
            if (5 not in Devices): Domoticz.Device(Name="Volume 2", Unit=5, Type=244, Subtype=73, Switchtype=7,  Image=8).Create()
            Domoticz.Log("Created Zone 2 device(s) because zone requested in hardware setup but device not found.")
        else:
            zone2Source = Devices[4].nValue
            if (5 in Devices): zone2Volume = int(Devices[5].sValue)
    else:
        pollingDict.pop("Z2")
        pollingDict["MU"] = "PW?\r"
        
    if (1 not in Devices):
        Domoticz.Device(Name="Power", Unit=1, TypeName="Switch",  Image=5).Create()
        if (2 not in Devices): Domoticz.Device(Name="Main Zone", Unit=2, TypeName="Selector Switch", Switchtype=18, Image=5, \
                        Options="LevelActions:"+stringToBase64(LevelActions)+";LevelNames:"+stringToBase64(Parameters["Mode3"])+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ==").Create()
        if (3 not in Devices): Domoticz.Device(Name="Main Volume", Unit=3, Type=244, Subtype=73, Switchtype=7,  Image=8).Create()
        Domoticz.Log("Created Main Zone devices because they were not found.")
    else:
        mainSource = Devices[2].nValue
        if (3 in Devices): mainVolume1 = int(Devices[3].sValue)
        
    DumpConfigToLog()
    dictValue=0
    for item in Parameters["Mode3"].split('|'):
        selectorMap[dictValue] = item
        dictValue = dictValue + 10
    Domoticz.Transport("TCP/IP", Parameters["Address"], Parameters["Port"])
    Domoticz.Protocol("Line")
    Domoticz.Connect()
    return

def onConnect(Status, Description):
    global isConnected, powerOn
    if (Status == 0):
        isConnected = True
        Domoticz.Log("Connected successfully to: "+Parameters["Address"]+":"+Parameters["Port"])
        Domoticz.Send('PW?\r')
    else:
        isConnected = False
        powerOn = False
        Domoticz.Log("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"])
        Domoticz.Debug("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"]+" with error: "+Description)
        SyncDevices()
    return

def onMessage(Data, Status, Extra):
    global oustandingPings, lastMessage, selectorMap, powerOn, pollingDict, ignoreMessages
    global mainSource, mainVolume1, zone2Source, zone2Volume, zone3Source, zone3Volume

    oustandingPings = oustandingPings - 1
    strData = Data.decode("utf-8", "ignore")
    Domoticz.Debug("onMessage called with Data: '"+str(strData)+"'")
    
    strData = strData.strip()
    action = strData[0:2]
    detail = strData[2:]
    if (action in pollingDict): lastMessage = action

    if (action == "PW"):        # Power Status
        if (detail == "STANDBY"):
            powerOn = False
        elif (detail == "ON"):
            powerOn = True
        else: Domoticz.Debug("Unknown: Action "+action+", Detail '"+detail+"' ignored.")
    elif (action == "ZM"):      # Main Zone on/off
        if (detail == "ON"):
            mainVolume1 = abs(mainVolume1)
        elif (detail == "OFF"):
            mainSource = 0
            mainVolume1 = abs(mainVolume1)*-1
        else: Domoticz.Debug("Unknown: Action "+action+", Detail '"+detail+"' ignored.")
    elif (action == "SI"):      # Main Zone Source Input
        for key, value in selectorMap.items():
            if (detail == value):      mainSource = key
    elif (action == "MV"):      # Master Volume
        if (detail.isdigit()):
            mainVolume1 = int(detail[0:2])
        elif (detail[0:3] == "MAX"): Domoticz.Debug("Unknown: Action "+action+", Detail '"+detail+"' ignored.")
        else: Domoticz.Log("Unknown: Action "+action+", Detail '"+detail+"' ignored.")
    elif (action == "MU"):      # Overall Mute
        if (detail == "ON"):         mainVolume1 = abs(mainVolume1)*-1
        elif (detail == "OFF"):      mainVolume1 = abs(mainVolume1)
        else: Domoticz.Debug("Unknown: Action "+action+", Detail '"+detail+"' ignored.")
    elif (action == "Z2"):      # Zone 2
        if (detail.isdigit()):
            zone2Volume = int(detail[0:2])
        else:
            for key, value in selectorMap.items():
                if (detail == value):      zone2Source = key
            if (zone2Source == 0):  zone2Volume = abs(zone2Volume)*-1
            else:                   zone2Volume = abs(zone2Volume)*-1
    elif (action == "Z3"):      # Zone 3
        if (detail.isdigit()):
            zone3Volume = int(detail[0:2])
        else:
            for key, value in selectorMap.items():
                if (detail == value):      zone3Source = key
            if (zone3Source == 0):  zone3Volume = abs(zone3Volume)*-1
            else:                   zone3Volume = abs(zone3Volume)*-1
    else:
        if (ignoreMessages.find(action) < 0):
            Domoticz.Error("Unknown message '"+action+"' ignored.")
    SyncDevices()
    return

def onCommand(Unit, Command, Level, Hue):
    global selectorMap, powerOn

    Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))

    Command = Command.strip()
    action, sep, params = Command.partition(' ')
    delay = 0
    if (powerOn == False):
        Domoticz.Send('PWON\r')  # Any commands sent within 4 seconds of this will potentially be ignored
        delay = int(Parameters["Mode2"])
    if (action == "On"):
        if (Unit == 1):     Domoticz.Send(Message='ZMON\r', Delay=delay)
        elif (Unit == 2):   Domoticz.Send(Message='ZMON\r', Delay=delay)
        elif (Unit == 3):   Domoticz.Send(Message='MUOFF\r', Delay=delay)
        elif (Unit == 4):   Domoticz.Send(Message='Z2ON\r', Delay=delay)
        elif (Unit == 5):   Domoticz.Send(Message='Z2MUOFF\r', Delay=delay)
        elif (Unit == 6):   Domoticz.Send(Message='Z3ON\r', Delay=delay)
        elif (Unit == 7):   Domoticz.Send(Message='Z3MUOFF\r', Delay=delay)
        else: Domoticz.Error( "Unknown Unit number in command "+str(Unit)+".")
    elif (action == "Set"):
            if (params.capitalize() == 'Level') or (Command.lower() == 'Volume'):
                if (Unit == 2):     # Main selector
                    Domoticz.Send(Message='SI'+selectorMap[Level]+'\r', Delay=delay)
                elif (Unit == 3):   # Volume control
                    Domoticz.Send(Message='MV'+str(Level)+'\r', Delay=delay)
                elif (Unit == 4):   # Zone 2 selector
                    Domoticz.Send(Message='Z2'+selectorMap[Level]+'\r', Delay=delay)
                elif (Unit == 5):   # Zone 2 Volume control
                    Domoticz.Send(Message='Z2'+str(Level)+'\r', Delay=delay)
                elif (Unit == 6):   # Zone 3 selector
                    Domoticz.Send(Message='Z3'+selectorMap[Level]+'\r', Delay=delay)
                elif (Unit == 7):   # Zone 3 Volume control
                    Domoticz.Send(Message='Z3'+str(Level)+'\r', Delay=delay)
                SyncDevices()
    elif (action == "Off"):
        if (Unit == 1):     Domoticz.Send(Message='ZMOFF\r', Delay=delay)
        elif (Unit == 2):   Domoticz.Send(Message='ZMOFF\r', Delay=delay)
        elif (Unit == 3):   Domoticz.Send(Message='MUON\r', Delay=delay)
        elif (Unit == 4):   Domoticz.Send(Message='Z2OFF\r', Delay=delay)
        elif (Unit == 5):   Domoticz.Send(Message='Z2MUON\r', Delay=delay)
        elif (Unit == 6):   Domoticz.Send(Message='Z3OFF\r', Delay=delay)
        elif (Unit == 7):   Domoticz.Send(Message='Z3MUON\r', Delay=delay)
        else: Domoticz.Error( "Unknown Unit number in command "+str(Unit)+".")
    else:
        Domoticz.Error("Unhandled action '"+action+"' ignored, options are On/Set/Off")
    return

def onDisconnect():
    global isConnected, powerOn
    isConnected = False
    powerOn = False
    Domoticz.Log("Denon device has disconnected.")
    SyncDevices()
    return

def onHeartbeat():
    global isConnected, nextConnect, oustandingPings, lastMessage, pollingDict
    if (isConnected == True):
        if (oustandingPings > 5):
            Domoticz.Disconnect()
            nextConnect = 0
        else:
            Domoticz.Send(pollingDict[lastMessage])
            Domoticz.Debug("onHeartbeat: lastMessage "+lastMessage+", Sending '"+pollingDict[lastMessage][0:2]+"'.")
            oustandingPings = oustandingPings + 1
    else:
        # if not connected try and reconnected every 3 heartbeats
        oustandingPings = 0
        nextConnect = nextConnect - 1
        if (nextConnect <= 0):
            nextConnect = 3
            Domoticz.Connect()
    return

def SyncDevices():
    global powerOn, mainSource, mainVolume1, zone2Source, zone2Volume, zone3Source, zone3Volume
    
    if (powerOn == False):
        UpdateDevice(1, 0, "Off")
        UpdateDevice(2, 0, "0")
        UpdateDevice(3, 0, str(abs(mainVolume1)))
        UpdateDevice(4, 0, "0")
        UpdateDevice(5, 0, str(abs(zone2Volume)))
        UpdateDevice(6, 0, "0")
        UpdateDevice(7, 0, str(abs(zone3Volume)))
    else:
        UpdateDevice(1, 1, "On")
        UpdateDevice(2, mainSource, str(mainSource))
        if (mainVolume1 <= 0): UpdateDevice(3, 0, str(abs(mainVolume1)))
        else: UpdateDevice(3, 2, str(mainVolume1))
        UpdateDevice(4, zone2Source, str(zone2Source))
        if (zone2Volume <= 0): UpdateDevice(5, 0, str(abs(zone2Volume)))
        else: UpdateDevice(5, 2, str(zone2Volume))
        UpdateDevice(6, zone3Source, str(zone3Source))
        if (zone3Volume <= 0): UpdateDevice(7, 0, str(abs(zone3Volume)))
        else: UpdateDevice(7, 2, str(zone3Volume))
    return

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

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')

Re: Plugin Denon AVR-X2100W

Posted: Sunday 12 March 2017 9:32
by Dnpwwo
@G3rard,

The "Async Read Exception: 125, Operation canceled" is nothing to worry about, Unix seems to throw that during a plugin forced shutdown sometimes but it isn't a problem.

I haven't seen the "PluginList: Error 'Error document empty.' at line 0 column 0 in XML'." error. How many plugins do you have on your system? Is it just the one?

Re: Plugin Denon AVR-X2100W

Posted: Sunday 12 March 2017 10:57
by G3rard
@Dnpwwo,
I have some other plugins on the system (Sonos, Kodi, Rain prediction (Buienradar)).
The pluginlist error appeared for the first time after I changed the Denon script regarding the ignoredMessages.