Things to do with your network-connected Denon/Marantz receiver

This post will focus on the things you can do with your network-connected Denon/Marantz receiver. I bought my Denon AVR-3808 in 2007, so it’s actually my very first IoT device. Unfortunately my receiver doesn’t support the newer HTTP/XML-based protocol or streaming services, but the old telnet-based AVR protocol still gives a lot of opportunities.

So without further ado, a walk-through of options I know of…

App control
Denon doesn’t support the AVR protocol in their app, so third party apps are the only options for me. If you have a newer receiver you won’t have that problem. I’ve been using AVR-Remote for Denon/Marantz for years. It’s a bit old, but still works.

Control with Yatse
Another use within Android is volume control and more within Yatse. Yatse is a full-featured Kodi remote control app and much more. If you have a Kodi media center and an Android device, you should definately give Yatse a chance. And if you use Yatse and own a Denon/Marantz receiver, you should try the Denon/Marantz plugin. Please note that this is a shameless recommendation, since I’m the developer of this plugin.

Control with Tasker
Into automation and using Tasker? Yet another use within Android. Use Denon/Marantz plugin to automate interaction with your receiver. Yes, this is the same plugin as mentioned in previous chapter. Example usages:

  • Mute receiver when phone rings.
  • Use as clockradio: Turn on receiver on radio at 6:00 in the morning.
  • Turn off the receiver when leaving home.
  • Well, whatever you can think of.

openHAB
Staying with automation, integrate your receiver into your home automation when using openHAB. I’m not using this binding myself, since it constantly occupies the only connection available for the AVR, so it would block all other usages. If you have a newer receiver, you won’t have that problem. Instead, I can integrate through the Logitech Harmony binding.

Linux shell script
I wrote this small script years ago and scheduled it to to be run by cron daemon on my server at midnight. Purpose was to save energy in case I’d forgotten to turn off my receiver. It demonstrates how to send a simple command from a shell script, but other than that it’s obsoleted today by openHAB rules or similar.

#!/bin/bash
# Written by Jacob Laursen , 2009-2011.
#
# This script turns off a Denon receiver if none of the listed
# hosts to be checked are up and running.
#
# Options:
# --force : Skip host checking, just turn it off.

HOST_CHECK=`echo {"ps3","smarttv"}`
HOST_DENON="denon"

standby ()
{
        {
                sleep 2
                echo -n -e "PWSTANDBY\r"
                sleep 2
        } | telnet >/dev/null 2>&1 $HOST_DENON
}

if [ "$1" == "--force" ]; then
        standby
        if [ $? == 0 ]; then
                echo "Power turned off"
        else
                echo "Already turned off"
        fi
        exit
fi

host_up=0

for host in ${HOST_CHECK}
do
        ping >/dev/null -c 1 $host

        if [ $? == 0 ]; then
                host_up=1
                break
        fi
done

if [ $host_up == 0 ]; then
        standby
fi

Logitech Media Server/Squeezebox plugin
For controlling volume from my Squeezebox Receiver I’m using DenonSerial v0.1.42 extension by Peter Watkins. I’m not sure where to find it today, as it’s quite old – but still working nicely. An alternative might be DenonAvpControl, but I haven’t tried that.

The purpose of this extension is to set fixed volume to 100% on the Squeezebox Receiver and instead control volume on the Denon receiver. Using this extension should work no matter how you control your Squeezebox Receiver. However, the app (or whatever) must support sending volume commands even for players with fixed volume configured. The Android app Squeeze Ctrl supports this. The ancient, but still excellent, Squeeze Commander does not.

Playing with WeMo Insight Switch

I finally couldn’t resist getting my hands on a WeMo Insight Switch anymore. It’s a kind of expensive gadget, considering how clumsy it is and that all it can do is turn one thing on or off. Also, I read in some specifications that it was consuming a considerable amount of energy itself. However, I’m the unlucky owner of a Thomson modem from the Danish ISP Stofa, and this thing consumes about 12.4 W, so I’ve been wanting to do something about that for a while, since I’m only using it for my backup internet connection (WAN 2) and for IP telephony.

Unpackaging
Just kidding. After connecting the switch you have to install the 33 MB app from Belkin to get it up running. After this I searched the net for API’s and alternate ways to control it. Half an hour later I had a working curl command to turn it on or off, as well as a working Tasker configuration using RESTask for Tasker, which I just found for the job (since Tasker doesn’t seem to support setting custom headers in HTTP POST requests).

The hardware
Before jumping to my first project/solution, a few words on the hardware:

  • Power consumption: When the relay is off, it consumes approx. 1.5 W. When on, approx. 1.7 W.
  • Socket: The socket is a Schuko socket, which is problematic for the Danish market, since you cannot plug in the traditional Danish flat and round connectors – they physically don’t fit in.

Controlling WeMo from Tomato
Since my Tomato router firmware (by Shibby) comes with curl preinstalled, controlling WeMo from the router is not a problem. What I wanted to do was having my router turn on the modem for WAN 2 when WAN 1 is down. I decided to ping the DNS server to check if I’m connected to the internet, and to do this once a minute. So in Administration/Scheduler I added this custom script to run every minute:

# Turn on WeMo when WAN is down, hoping for WAN2...
if ! ping >/dev/null -c 1 8.8.8.8; then
  curl -d '<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:SetBinaryState xmlns:u="urn:Belkin:service:basicevent:1"><BinaryState>1</BinaryState></u:SetBinaryState></s:Body></s:Envelope>' -H 'SOAPACTION: "urn:Belkin:service:basicevent:1#SetBinaryState"' -H 'Content-Type: text/xml; charset="utf-8"' -X POST http://wemo.local:49153/upnp/control/basicevent1
fi

After switching over to WAN 2, DNS will still be unavailable for a while – and yes, this method will try to turn on the WeMo over and over again. However, this shouldn’t really cause any problems if it’s already turned on. On the other hand, it might actually save the day, if the first packet is lost (WeMo is on Wi-Fi).

Next project
Next project will be to set up openHAB on a Raspberry Pi (for starters) and try to teach it when at least one person is at home. Then I can have back my IP telephony (requiring the modem on) when arriving at home and until going to bed.

Pear upgrade broken

I haven’t been able to upgrade Horde for a few months:

Error getting channel info from pear.horde.org: Connection to `ssl://pear.horde.org:443' failed:

Today I finally digged into the issue. The short explanation and fix in my case was:

# php -r "print_r(openssl_get_cert_locations());"
Array
(
    [default_cert_file] => /usr/local/ssl/cert.pem
    [default_cert_file_env] => SSL_CERT_FILE
    [default_cert_dir] => /usr/local/ssl/certs
    [default_cert_dir_env] => SSL_CERT_DIR
    [default_private_dir] => /usr/local/ssl/private
    [default_default_cert_area] => /usr/local/ssl
    [ini_cafile] =>
    [ini_capath] =>
)
# ll /usr/local/ssl/cert.pem
ls: /usr/local/ssl/cert.pem: No such file or directory
# cd /usr/local/ssl
# wget --no-check-certificate https://curl.haxx.se/ca/cacert.pem
# mv cacert.pem cert.pem

Problem solved. Completely unrelated to Horde. Might have been caused by a PHP or OpenSSL upgrade at some point, I guess.

Miele@mobile 2.02

By incident I found out yesterday that the Miele@mobile app was updated in Google Play back in May. For some reason Pushbullet didn’t notify me, and I’m not allowed to download the app from Google Play myself, since I’m resided in Denmark and Miele@home is not supported here. Strangely, the only visible change I found in this update since 2.01 was a complete Danish translation. Nice – hopefully this means that Miele@home support in Denmark is not too far away. Update, September 6th 2016: I just found out that the geo-restriction in Google Play is also gone, or at least expanded to include Denmark. It’s now also possible to select Miele Denmark as origin for the Miele user account.

Today’s small rant:

  • Why this geoblocking? I’m allowed within EU to buy all the hardware in Germany, but the only app that exists for the system, I’m not allowed to use. With my very expensive appliances and Miele@home gateway/modules I might add. Luckily in Android there are ways to get the app anyway, but my girlfriend can’t download the app for iPhone and use the system at all.
  • Why not open up the new JSON-RPC API, so better 3rd party apps could be written, that didn’t have to depend only on the old broken Homebus protocol? This would make the system more useful since new ways to use the sytem would arise.

Miele XGW 3000 firmware 2.03

For quite some time, I’ve been holding back a post introducing my Miele@home Android project. So in the wrong order, here’s an attempt to get in touch with some fellow Miele@home geeks: Sharing my findings about the new XGW 3000 firmware upgrade, which was released last week.

My findings are only about the Homebus protocol and multicast packets, since the new JSON-RPC protocol isn’t for public consumption (or so it seems). So here we go – changes since version 2.0.0:

  • Element ‘type’ in http://<gateway>/homebus/ seems to be working again (e.g. <type>WMV960</type>). I’ve never seen this work since the original firmware of my gateway (1.1.0).
  • Prior to 2.0.3, multicast packets would refer to a ZigBee MAC address (at least when communicating with XKM 3000 Z modules): “id=hdm:ZigBee:<MAC>”. This is now changed to device UID.
  • For some devices numeric values are now included in the http://<gateway>/homebus/device XML:
    <key name="State" value="Running" type="state" raw="5"/>
    <key name="Program" value="Cottons" type="program" raw="1"/>
    <key name="Phase" value="Rinses" type="phase" raw="5"/>
    

    This is true for my WMV 960, but not my TKR 350 WP or H 5581 BP. They all have the XKM 3000 Z module, but the WMV has firmware version 1.16, while the other two are version 1.02 (does anyone know if these modules are firmware-upgradeable and/or where to find a changelog?).

Bugs still present:

  • Language parameter not respected for http://<gateway>/homebus/device?language=en. Gateway language is always used.
  • Bizarre values for key “Start Time”. Will update the post on this later.

That’s it for now. I’ll return later with more information about my project as well as rants about the Homebus protocol and Miele’s secrecy and lack of support.

Synology DS cloud broken

The latest version of Synology’s Android app DS cloud stopped working with the Cloud Station package on my DS508, which is stuck with DSM 4.0. The app was released on Google Play March 2nd 2016 – version 2.6. Cloud Station package version is 2.2-3047.

CloudStation is running on the DS. My Android phones and tablet are shown as offline in the client list. On the devices DS cloud is shown as running, but no files are synchronized. Synchronization is missing both ways – files are not pushed to the phone, and files updated on the phone are not pushed to the DS.

To fix this I went to apkpure.com and downloaded version 2.5 of the app. Before installing, the existing app has to be uninstalled, so reconfiguration is needed.

I created a support ticket at synology.com, so they are informed.

Update, March 10th 2016: Synology reported back to me that they had analyzed my logs and found the problem: The database was corrupted. So it must be a bug in the database upgrade in version 2.6 of the app. After clearing the app data and reconfiguring it works perfectly.

Building PHP after installing MySQL 5.7

I got the following error when trying to build PHP 5.6.14/5.6.15 after upgrading to MySQL 5.7:

configure: error: Cannot find libmysqlclient_r under /usr/local/mysql.
Note that the MySQL client library is not bundled anymore!

I added this to my build script in order to create the missing symbolic links:

cd /usr/local/mysql/lib
for f in libmysqlclient.so*; do ln -s $f $(echo $f | sed s/libmysqlclient/libmysqlclient_r/); done
ln -s libmysqlclient.a libmysqlclient_r.a

Denon receiver plugin for Yatse

I probably made my most niche thing ever today: A plugin for an Android app. I found out yesterday that a new API for Yatse was made available, so today I took on the challenge, and created a plugin for my Denon A/V receiver. I can now control the volume on my receiver directly from Yatse. In a few days I might clean the code up and finish it, so it can be released either here or on Google Play.

Update, August 8th 2015: I’ve just released the plugin!
Get it on Google Play.

Raspbmc and NFS permissions

NFS is often used for accessing network shares from Raspbmc, due to its low overhead. Many tutorials describe how to set this up, for example with a Synology NAS. One subject isn’t covered much, though: A setup with restrictive permissions.

On my Synology my media files are usually owned by me, and has ‘dlna’ as group with read-only permissions. Example:

drwxr-x---  9 jacob dlna   4096 Jun 15  2012 video

On the NAS I have created a user for Raspbmc and made it a member of this group:

DiskStation> cat /etc/group | grep dlna
dlna:x:65536:admin,jacob,raspbmc
DiskStation> cat /etc/passwd | grep raspbmc
raspbmc:x:1046:100:Raspberry Pie XBMC:/var/services/homes/raspbmc:/sbin/nologin

To get this to work on the Raspberry I’ve first had to synchronize the GID/UID’s. Since the NAS is the master, I’ve done this on the Raspberry (logged in as the pi user):

pi@raspbmc:~$ sudo groupadd -g 65536 dlna
pi@raspbmc:~$ sudo usermod -a -G dlna pi

After enabling root access, I’ve changed the pi user to match the UID of the raspbmc user on the NAS:

root@raspbmc:~# usermod -u 1046 pi

(For this to work I had to kill a number of processes first)

Changing UID of the pi user will cause a lot of trouble for Raspbmc, which expects the user to have UID 1000. This is hardcoded in at least two scripts:

  • /opt/xbmc-bcm/xbmc-bin/share/xbmc/addons/script.raspbmc.settings/default.py
  • /opt/xbmc-bcm/xbmc-bin/share/xbmc/addons/script.raspbmc.settings/autostart.py

Fix this by adding:

sed -i 's/getpwuid(1000)/getpwuid(1046)/g' /opt/xbmc-bcm/xbmc-bin/share/xbmc/addons/script.raspbmc.settings/default.py
sed -i 's/getpwuid(1000)/getpwuid(1046)/g' /opt/xbmc-bcm/xbmc-bin/share/xbmc/addons/script.raspbmc.settings/autostart.py

to /etc/rc.local so the scripts are automatically fixed during startup. Replace 1046 with your pi UID.

Without this fix automatic updates won’t work, and you’ll see script errors during startup – and can’t launch the Raspbmc settings.

httpd.pid gone missing

For quite some time I’ve been having a problem with my httpd.pid file going missing every now and then. Whenever this happens, I can’t use the init script to start and stop the server anymore, which is pretty annoying. For some reason I had learned to live with this – I would just ‘killall httpd’, start the server again and the httpd.pid would be back for some time, until the problem would reappear.

Finally I decided to do something about it. I added this small script to my hourly cron jobs:

if [ ! -e "/usr/local/apache2/logs/httpd.pid" ]; then
        echo "httpd.pid missing"
fi

A few weeks later this trap was finally triggered – less than an hour after my daily logrotate, which produced this output:

Starting httpd: [  OK  ]
Stopping httpd: [  OK  ]
(repeated a number of times...)
Starting httpd: [  OK  ]
Stopping httpd: [FAILED]
Starting httpd: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs
[FAILED]
error: error running postrotate script for /usr/local/apache2/logs/*_log 

This was not the first time I had seen this, but it was the first time I realized that the logrotate problem was causing the httpd.pid problem, and not the other way around.

So I checked my /etc/logrotate.d/apache config file:

/usr/local/apache2/logs/*_log {
    rotate 1024
    size 4M
    notifempty
    postrotate
        /etc/init.d/httpd restart
    endscript
}

After a few minutes of reading the logrotate man page, I realized what was wrong (had a hunch, though): The restart between the postrotate/endscript directives was performed for each logfile, i.e. multiple times, instead of just a single time after the last one was rotated. This in itself is pretty bad, but it would also happen asynchronously, thus create a mess. This problem was easily solved using the sharedscript directive. Also, a simple “reload” instead of “restart” is sufficient to make httpd reopen the logfiles, thus create new filehandles.

After fixing these two problems, the file ended up like this:

/usr/local/apache2/logs/*_log {
    rotate 1024
    size 4M
    notifempty
    sharedscripts
    postrotate
        /etc/init.d/httpd reload
    endscript
}

I’m fully expecting this to solve the problem once and for all.