Denon
AV receiver Denon / Marantz
Below a description how to integrate a Denon/Marantz receiver in Domoticz.
All scripts were created and tested on a Denon AVR-X1000, for Marantz or other Denon models it might be required to make some small changes. Goal is to make the setup and scripts compatible with both Makes and models.
This page is based on information found on this page: forum which contains a rough sketch how to implement your Denon into domoticz.
Basic concept
The AV receiver is controlled by dummy devices configured in Domoticz. Although the actions can be triggered in different ways I chose to create one Lua script which is triggered on a Domoticz device change. This way everything is in one place and actions triggered by the dummy device directly caused unjust errors in the Domoticz logs.
The synchronization is done via a bash scripts which runs every 60 seconds via the cron tab. For updating the Power status an additional dummy device is configured as a slave to the Power Switch to prevent loop switching.
The goal is to match the behavior of the receiver and Domoticz as closely as possible, e.g in my case I customized the source inputs names matching my specific application and adopting these into Domoticz. In addition I was able to match the sound levels from the device to the domoticz control.
Currently supported functions:
-- Power On/Off
-- Mute On/Off
-- Volume +/-
-- Select source input
To be implemented:
-- Run as service (higher frequent than 60 seconds)
-- Siri support
-- ....
Prerequisites
bc command must be installed
Setup
Input sources configuration:
Denon receiver
1. Setup custom input source names
Setup > Inputs > Source Rename > CBL/SAT = AMINO DVD = KODI Blu-ray = CHROMECAST GAME = PLAYSTATION3
2. Configure volume display
Setup > Audio > Volume > Scale = 0-98
Domoticz devices
1. Add Dummy devices in Domoticz
Setup > Hardware > Type = "Dummy" > Add
2. Create DENON_VOLUME
Setup > Hardware > "Create Virtual Sensor" => Name: "DENON_VOLUME" Sensor Type: "Dimmer" OK
3. Create DENON_SOURCE
Setup > Hardware > "Create Virtual Sensor" > Name: "DENON_SOURCE" Sensor Type: "Selector" OK
4. Configure DENON_SOURCE
Switches > "DENON_SOURCE" > Edit > Level 10 Name: "AMINO" Level 20 Name: "KODI" Level 30 Name: "CHROMECAST" Level 40 Name: "PLAYSTATION3" Save
Lua Script
1. Goto Domoticz > Setup > Events
2. Select Lua
3. Enter an "Event Name"
4. Copy script below into the editing field
5. Change the values in the section "Definitions" to your specific values
6. Select "Device" in stead of "All" <==== IMPORTANT otherwise you will get unjust errors in the Domoticz log.
7. Make sure "Event active" is checked and save script
-- Control AV receiver (Denon or Marantz)
--
-- Author: Bart77
-- Version: 1.2
--
-- Credits:
-- TrixWood to provide a initial version on the forum
--
-- This script will execute actions triggered by virtual devices in Domoticz
-- to control a Denon/Marantz AV receiver.
--
-- Currently supported functions:
-- Power On/Off
-- Source Input select
-- Mute On/Off
-- Volume +/-
--
-- 1.2 Removed DENON_POWER object, became obsolete by Input Source select
-- 1.1 Added update on Input Source select
-- 1.0 First release
--
-- Definitions
IP = 'xxx.xxx.xxx.xxx'
RECEIVER_VOLUME = "DENON_VOLUME" -- Control MUTE and VOLUME
RECEIVER_SOURCE = "DENON_SOURCE" -- Control OFF and Select Input Source (= ON)
-- Main script
commandArray = {}
if devicechanged[RECEIVER_VOLUME] then -- MUTE and VOLUME
if (otherdevices[RECEIVER_VOLUME] == "Off") then
os.execute ("curl http://" .. (IP) .. "/MainZone/index.put.asp?cmd0=PutVolumeMute%2Fon");
print ("Device:" .. RECEIVER_VOLUME .. " send command Mute = On");
else
NewLevel = otherdevices_svalues[RECEIVER_VOLUME] - 80 ; -- Apply offset from absolute to relative
NewLevel = math.min(NewLevel, 9.5); -- Top Domoticz Scale
os.execute ("curl http://" .. (IP) .. "/MainZone/index.put.asp?cmd0=PutVolumeMute%2Foff");
os.execute ("curl http://" .. (IP) .. "/MainZone/index.put.asp?cmd0=PutMasterVolumeSet/" .. (NewLevel));
print ("Device:" .. RECEIVER_VOLUME .. " send command Mute = Off; Set Volume = " .. NewLevel);
end
elseif devicechanged[RECEIVER_SOURCE] then -- OFF or INPUT SOURCE SELECT
-- Translate Selector Switch Level to SourceToSet
if (otherdevices_svalues[RECEIVER_SOURCE] == '0' ) then
SourceToSet = "Off";
elseif (otherdevices_svalues[RECEIVER_SOURCE] == '10' ) then
SourceToSet = "SAT/CBL";
SourceCustomName = "AMINO";
elseif (otherdevices_svalues[RECEIVER_SOURCE] == '20' ) then
SourceToSet = "DVD";
SourceCustomName = "KODI";
elseif (otherdevices_svalues[RECEIVER_SOURCE] == '30' ) then
SourceToSet = "BD";
SourceCustomName = "CHROMECAST";
elseif (otherdevices_svalues[RECEIVER_SOURCE] == '40' ) then
SourceToSet = "GAME";
SourceCustomName = "PLAYSTATION3";
else
SourceToSet = "Unknown";
end
if ( SourceToSet == 'Unknown' ) then
print ("WARNING: Device:" .. RECEIVER_SOURCE .. " unkown source input" );
elseif ( SourceToSet == 'Off' ) then -- Switch Off receiver
os.execute ("curl http://" .. (IP) .. "/MainZone/index.put.asp?cmd0=PutZone_OnOff%2FOFF" );
print ("Device:" .. RECEIVER_SOURCE .. " send command set source input = OFF");
else -- SwitchSource to SourceToSet
os.execute ("curl http://" .. (IP) .. "/MainZone/index.put.asp?cmd0=PutZone_InputFunction%2F" .. (SourceToSet) );
print ("Device:" .. RECEIVER_SOURCE .. " send command set source input = " .. (SourceToSet) .. ". => " .. (SourceCustomName) );
end
end
return commandArray
Bash Script
1) Create a bash file in /home/pi/domoticz/scripts
2) Copy the script below into the file and save
3) Add this script into to the crontab
#!/bin/bash
# ---------- Declarations ---------------------------------------------------------------------
# Script
VERSION="1.0" # Script version
LOG="/dev/tty" # Default log to terminal
# Settings Receiver = Device
DEVICE_IP="xxx.xxx.xxx.xxx" # Device IP Address
DEVICE_TYPE="Undefined" # Device type read from device
DEVICE_STATUS="Undefined" # Device status read from device
DEVICE_VOLUME_SCALE="Undefined" # Volume scale [Relative/Abolute] <=== Only display value , value read will always be Relative
DEVICE_VOLUME_OFFSET=80 # Volume offset [dB to Abolute]
DEVICE_XML=(
'Deviceinfo.xml'
'formMainZone_MainZoneXmlStatus.xml'
'formMainZone_MainZoneXml.xml'
'formNetAudio_StatusXml.xml'
) # Source types read from device
# Settings Domoticz
DOMO_IP="192.168.77.10" # Domoticz IP Address
DOMO_PORT="8080" # Domoticz Port
DOMO_DEVICE_POWER_IDX="115" # On/Off (Switch) IDX
DOMO_DEVICE_POWER_STATUS_IDX="123" # Status (Switch) IDX slave (On/Off)
DOMO_DEVICE_VOL_ABS_IDX="122" # Absolute Volume (Slider) IDX
# ---------- Usage ---------------------------------------------------------------------
SCRIPT_USAGE()
{
echo "usage: avreceiver.sh [-h] {-l]
This script will synchronize the status of a AV receiver (Denon / Marantz) with Domoticz.
Supported device types:
DENON '*AVR-X1000'
... Additional models to be added/tested
Version: $VERSION
Author: BDV77
[-h] = Help, display usage.
[-l] = Log to file 'avreceiver.log' instead of terminal
Version history:
1.0 First release
0.1 Based on Denon script of Trixwood V0.3
to do:
Get source input names from device
Get custom source input names from device
"
}
# ---------- Read input arguments ---------------------------------------------------------------------
while [ "$1" != "" ]; do
case $1 in
-h | --help ) SCRIPT_USAGE
exit
;;
-l ) LOG="avreceiver.log"
;;
* ) SCRIPT_USAGE
exit 1
esac
shift
done
# ---------- Functions -------------------------------------------------------------------------
# ---------- Main function ---------------------------------------------------------------------
echo "$(date +%k:%M:%S.%N) Started avreceiver.sh" > $LOG
# Check if Domiticz status is online and service is running
PINGTIME=$(ping -c 1 -q "$DOMO_IP" | awk -F"/" '{print $5}' | xargs)
if ! expr $PINGTIME '>' 0 &> /dev/null ; then
echo "Domoticz status = Offline [responsetime = $PINGTIME]" >> $LOG
exit
fi
if [[ "$(curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=getversion" | grep "Domoticz")" == "" ]] ; then
echo "Domoticz status = Onine but Domoticz service is not running" >> $LOG
exit
fi
echo "Domoticz status = Online [responsetime = $PINGTIME] and Domoticz service is running" >> $LOG
# Check if device is online and verify identity
PINGTIME=$(ping -c 1 -q "$DEVICE_IP" | awk -F"/" '{print $5}' | xargs)
if ! expr PINGTIME '>' 0 &> /dev/null ; then
echo "Device = Offline [responsetime = $PINGTIME]" >> $LOG
# Set status to offline
# Define default offline status in Domoticz
fi
echo "Device = Online [responsetime = $PINGTIME]" >> $LOG
# Get device type and try to identity
i=0
for XML in ${DEVICE_XML[@]}; do # Load device data
XML_DATA[$i]="$(curl -s "http://$DEVICE_IP/goform/$XML")"
i=$(($i+1))
done
DEVICE_TYPE=$(echo ${XML_DATA[0]} | grep -oPm1 "(?<=<ModelName>)[^<]+")
case $DEVICE_TYPE in
"") #Nothing found --> not a AV receiver
echo "No device type <ModelName> could be retreived from $DEVICE_IP/goform/Deviceinfo.xml" >> $LOG
exit
;;
"*AVR-X1000") #Add other device types that are identical
echo Succesfully identified a supported device type: $DEVICE_TYPE >> $LOG
;;
# "") #Add other device types here and define differences!
# ...
# ;;
*) #Default to *AVR-X1000??
echo "An unsupported device type <ModelName> was retreived from $DEVICE_IP/goform/Deviceinfo.xml = $DEVICE_TYPE, Default to *AVR-X1000" >> $LOG
DEVICE_TYPE="*AVR-X1000"
esac
# ---------- Update Power (via slave device) ---------------------------------------------------------------------
POWER_STATUS=$(echo ${XML_DATA[1]} | grep -oPm1 "(?<=<Power><value>)[^<]+") #Read current values from xml data
POWER_STATUS="$(tr '[:lower:]' '[:upper:]' <<< ${POWER_STATUS:0:1})$(tr '[:upper:]' '[:lower:]' <<< ${POWER_STATUS:1})" # Convert to Capitalized, syntax from device is inconsistant
POWER_OLD=$(curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=devices&rid=$DOMO_DEVICE_POWER_IDX" | grep "Status" | cut -d'"' -f4 ) # Get old values from Domoticz
if [ "$POWER_STATUS" != "$POWER_OLD" ] ; then #Only update in case of difference
curl -s -i -H "Accept: application/json" "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$DOMO_DEVICE_POWER_STATUS_IDX&switchcmd=$POWER_STATUS" &> /dev/null
echo "Domoticz Object: $DOMO_DEVICE_POWER_STATUS_IDX (POWER), updated to value = $POWER_STATUS" >> $LOG
else
echo "Domoticz Object: $DOMO_DEVICE_POWER_STATUS_IDX (POWER) in sync, value = $POWER_STATUS" >> $LOG
fi
# ---------- Update Mute and Volume ---------------------------------------------------------------------
DEVICE_MUTE=$(echo ${XML_DATA[1]} | grep -oPm1 "(?<=<Mute><value>)[^<]+");
DEVICE_MUTE="$(tr '[:lower:]' '[:upper:]' <<< ${DEVICE_MUTE:0:1})$(tr '[:upper:]' '[:lower:]' <<< ${DEVICE_MUTE:1})" # Convert to Capitalized, syntax from device is inconsistant
DEVICE_VOLUME_REL=$(echo ${XML_DATA[1]} | grep -oPm1 "(?<=<MasterVolume><value>)[^<]+") # Volume value always read relative from device
if [[ "$DEVICE_VOLUME_REL" == "--" ]]; then DEVICE_VOLUME_REL=$(echo "-$DEVICE_VOLUME_OFFSET" | bc) ; fi # Convert volume value in case "--"
DEVICE_VOLUME_ABS=$(echo "$DEVICE_VOLUME_OFFSET + "$DEVICE_VOLUME_REL"" | bc) # Calculate absolute volume value
DEVICE_VOLUME_ABS=$(printf "%.*f\n" 0 $DEVICE_VOLUME_ABS) # Round value, due to resolution of Domoticz slider
SLIDER_OLD=$(curl -s "http://$DOMO_IP:$DOMO_PORT/json.htm?type=devices&rid=$DOMO_DEVICE_VOL_ABS_IDX" | grep "Data" | cut -d'"' -f4 );
if [[ "$SLIDER_OLD" == "Off" ]]; then #Invert Off status of slider to Mute Status On
MUTE_OLD="On"
else #Invert On status of slider to Mute Status Off
MUTE_OLD="Off"
if [[ "$SLIDER_OLD" != "On" ]]; then #if actual value is displayed, read value
VOLUME_ABS_OLD=$(echo "$SLIDER_OLD" | grep -Eo '[0-9]{1,4}');
fi
fi
if [[ "$DEVICE_MUTE" != "$MUTE_OLD" ]]; then #Only update in case of difference
curl -s -i -H "Accept: application/json" "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$DOMO_DEVICE_VOL_ABS_IDX&switchcmd=$MUTE_OLD" &> /dev/null
echo "Domoticz Object: $DOMO_DEVICE_VOL_ABS_IDX (Mute), updated to value = $MUTE_OLD" >> $LOG
else
echo "Domoticz Object: $DOMO_DEVICE_VOL_ABS_IDX (Mute) in sync, value = $MUTE_OLD" >> $LOG
fi
if [[ "$DEVICE_VOLUME_ABS" != "$VOLUME_ABS_OLD" ]] && [[ "$DEVICE_MUTE" == "Off" ]]; then #Only update in case of difference and Mute = Off
curl -s -i -H "Accept: application/json" "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$DOMO_DEVICE_VOL_ABS_IDX&switchcmd=Set%20Level&level=$(($DEVICE_VOLUME_ABS + 1))" &> /dev/null
if [ "$DEVICE_VOLUME_ABS" = 0 ] ; then # If set to zero correct for auto switch to mute <=== THIS WILL SWICH EACH TIME BECAUSE VALUE ZERO WILL NOT BE DISPLAYED :(
curl -s -i -H "Accept: application/json" "http://$DOMO_IP:$DOMO_PORT/json.htm?type=command¶m=switchlight&idx=$DOMO_DEVICE_VOL_ABS_IDX&switchcmd=On" &> /dev/null
fi
echo "Domoticz Object: $DOMO_DEVICE_VOL_ABS_IDX (Volume), updated to value = $DEVICE_VOLUME_ABS" >> $LOG
else
echo "Domoticz Object: $DOMO_DEVICE_VOL_ABS_IDX (Volume) in sync, value = $DEVICE_VOLUME_ABS" >> $LOG
fi
echo "$(date +%k:%M:%S.%N) Stoppped avreceiver.sh" >> $LOG
exit 0