OpenRemote package for Synology NAS

When I originally created Synology packages for Java in 2011 I noticed that they are being referred to by some diverse projects, and one that caught my eye was OpenRemote. Since a NAS is a low power always-on system, it’s a perfect candidate to run home automation control software. OpenRemote aims to be the integration and control layer for a huge range of devices and sensors which use a substantial variety of protocols – as the project’s strapline summarizes:
OpenRemote is the Open Source Middleware for the Internet of Things.

OpenRemote-DSM

This new version of the package is a significant update to version of 2.6.2 of the OpenRemote Controller. I selected this version because the drools component has been updated so that OpenRemote will run on Java 8. I have integrated the application with DSM’s Package Center and the software icons will be shown in main DSM applications menu when the package is running (button in the top left corner):

OpenRemote-webui

To use the software you will need to register for an OpenRemote Designer 2.5 account here. You will have to purchase this via the order process but notice the discount code for personal use which brings the price back to zero. If you had already created designs on OpenRemote versions prior to 2.5 there is a migration process to transfer this to the new version, though it looks like the OpenRemote documentation is overdue a tidy – much of it is clearly outdated.

 

Synology Package Installation

  • In the Advanced tab of the DSM User control panel enable the User Home service.
  • In Synology DSM’s Package Center, click Settings and add my package repository:
    Add Package Repository
  • The repository will push its certificate automatically to the NAS, which is used to validate package integrity. Set the Trust Level to Synology Inc. and trusted publishers:
    Trust Level
  • OpenRemote appears to need the unlimited cryptography policy files for the Java Cryptography Extension which are not included by default. If you want to use the Synology Java package you will need to manually install these policy files yourself, however I would recommend using my own Java SE Embedded package which does this automatically. Read the instructions on that page carefully too. Ensure you select Unlimited Strength Cryptography in the package installation menu:
    Java-crypto
  • Browse the Community section in Package Center to install OpenRemote:
    Community-packages
    The repository only displays packages which are compatible with your specific model of NAS. The OpenRemote package contains no native binaries at all, so it will work on any NAS that can run Java. This package does now require at least DSM 5.0.
 

Notes

  • You will only be able to sync the Controller with your Designer account once you have designed something. Until then, the sync will fail. This is normal.
  • Since this package does not include native binaries, if you need drivers for additional devices such as USB serial dongles, USB Z-Wave adapters etc., you will need to find these elsewhere. Rather than duplicating effort I will defer to the expertise of fellow Synology package developer jadahl who seems to have this part covered already.
  • Previous versions of this package required a port change to TCP18581 for the controller which required a matching config change in OpenRemote Designer. This is no longer necessary since the Controller now uses TCP8688 by default which does not clash with any Synology services.
  • OpenRemote saves your designs in the cloud with your online account, and the controller syncs with those designs. This means that you can uninstall the package without losing your designs.
  • You can see the Controller’s log in Package Center
  • DSM Package Center installs the application to /var/packages/OpenRemote/target. If you need to edit config files, or look at other logs in detail via SSH – that’s where you’ll find them.
 

Package scripts

For information, here are the package scripts so you can see what it’s going to do. You can get more information about how packages work by reading the Synology 3rd Party Developer Guide.

installer.sh

#!/bin/sh

#--------OPENREMOTE installer script
#--------package maintained at pcloadletter.co.uk


DOWNLOAD_FILE="OpenRemote_Controller.zip"
DOWNLOAD_PATH="https://github.com/openremote/Controller/releases/download/v2.6.0_beta"
DOWNLOAD_URL="${DOWNLOAD_PATH}/${DOWNLOAD_FILE}"
EXTRACTED_FOLDER="OpenRemote-Controller"
DAEMON_USER="`echo ${SYNOPKG_PKGNAME} | awk {'print tolower($_)'}`"
DAEMON_PASS="`openssl rand 12 -base64 2>/dev/null`"
DAEMON_ID="${SYNOPKG_PKGNAME} daemon user"
ENGINE_SCRIPT="openremote.sh"
CATALINA_PID="${SYNOPKG_PKGDEST}/${SYNOPKG_PKGNAME}.pid"
#'ua' prefix means wget user-agent will be customized
INSTALL_FILES="ua${DOWNLOAD_URL}"
TEMP_FOLDER="`find / -maxdepth 2 -path '/volume?/@tmp' | head -n 1`"
source /etc/profile


pre_checks ()
{
  if [ -z ${JAVA_HOME} ]; then
    echo "Java is not installed or not properly configured. JAVA_HOME is not defined. " >> $SYNOPKG_TEMP_LOGFILE
    echo "Download and install the Java Synology package from http://wp.me/pVshC-z5" >> $SYNOPKG_TEMP_LOGFILE
    exit 1
  fi
  
  if [ ! -f ${JAVA_HOME}/bin/java ]; then
    echo "Java is not installed or not properly configured. The Java binary could not be located. " >> $SYNOPKG_TEMP_LOGFILE
    echo "Download and install the Java Synology package from http://wp.me/pVshC-z5" >> $SYNOPKG_TEMP_LOGFILE
    exit 1
  fi
  
  #is the User Home service enabled?
  if [ "`synogetkeyvalue /etc/synoinfo.conf userHomeEnable`" == "no" ]; then
    echo "The User Home service is not enabled. Please enable this feature in the User control panel in DSM." >> $SYNOPKG_TEMP_LOGFILE
    exit 1
  fi
}


preinst ()
{
  pre_checks
  cd ${TEMP_FOLDER}
  for WGET_URL in ${INSTALL_FILES}
  do
    WGET_FILENAME="`echo ${WGET_URL} | sed -r "s%^.*/(.*)%\1%"`"
    [ -f ${TEMP_FOLDER}/${WGET_FILENAME} ] && rm ${TEMP_FOLDER}/${WGET_FILENAME}
    #this will allow openremote.org to track the number of downloads from Synology users
    WGET_URL=`echo ${WGET_URL} | sed -e "s%^ua%--user-agent=Synology --referer=https://pcloadletter.co.uk/2011/10/25/openremote-package-for-synology/ %"`
    wget ${WGET_URL}
    if [ $? != 0 ]; then
      if [ -d ${PUBLIC_FOLDER} ] && [ -f ${PUBLIC_FOLDER}/${WGET_FILENAME} ]; then
        cp ${PUBLIC_FOLDER}/${WGET_FILENAME} ${TEMP_FOLDER}
      else     
        echo "There was a problem downloading ${WGET_FILENAME} from the official download link, " >> $SYNOPKG_TEMP_LOGFILE
        echo "which was \"${WGET_URL}\" " >> $SYNOPKG_TEMP_LOGFILE
        echo "Alternatively, you may download this file manually and place it in the 'public' shared folder. " >> $SYNOPKG_TEMP_LOGFILE
        exit 1
      fi
    fi
  done
  
  exit 0
}


postinst ()
{
  #create daemon user
  synouser --add ${DAEMON_USER} ${DAEMON_PASS} "${DAEMON_ID}" 0 "" ""
  
  #extract main archive
  cd ${TEMP_FOLDER}
  #DSM 6.0 no longer includes unzip, use 7z instead
  unzip ${TEMP_FOLDER}/${DOWNLOAD_FILE} || 7z x -y ${TEMP_FOLDER}/${DOWNLOAD_FILE} > /dev/null
  rm ${TEMP_FOLDER}/${DOWNLOAD_FILE}
  mv ${TEMP_FOLDER}/${EXTRACTED_FOLDER}/* ${SYNOPKG_PKGDEST}
  rmdir ${TEMP_FOLDER}/${EXTRACTED_FOLDER}
  chmod +x ${SYNOPKG_PKGDEST}/bin/${ENGINE_SCRIPT}
  
  #TCP port 8081 is in use on Synology so we need to move Catalina to another port - 18581
  #This regex was tricky, but possible thanks to http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/
  #sed -i -n '1h;1!H;${;g;s%\(<Connector executor="HTTP-ThreadPool".*port="\)8080\(".* />\)%\118581\2%;p;}' ${SYNOPKG_PKGDEST}/conf/server.xml
  #sed -i "s/^webapp.port=.*$/webapp.port=18581/" ${SYNOPKG_PKGDEST}/webapps/controller/WEB-INF/classes/config.properties

  #change owner of folder tree
  chown -R ${DAEMON_USER} ${SYNOPKG_PKGDEST}

  #determine the daemon user homedir and save that variable in the user's profile
  #this is needed because new users seem to inherit a HOME value of /root which they have no permissions for
  DAEMON_HOME="`cat /etc/passwd | grep "${DAEMON_ID}" | cut -f6 -d':'`"
  su - ${DAEMON_USER} -s /bin/sh -c "echo export HOME=\'${DAEMON_HOME}\' >> /var/services/homes/${DAEMON_USER}/.profile"
  su - ${DAEMON_USER} -s /bin/sh -c "echo export CATALINA_PID=\'${CATALINA_PID}\' >> /var/services/homes/${DAEMON_USER}/.profile"

  #add firewall config
  /usr/syno/bin/servicetool --install-configure-file --package /var/packages/${SYNOPKG_PKGNAME}/scripts/${SYNOPKG_PKGNAME}.sc > /dev/null
  
  exit 0
}


preuninst ()
{
  `dirname $0`/stop-start-status stop
  
  exit 0
}


postuninst ()
{
  #remove daemon user
  synouser --del ${DAEMON_USER}

  #remove firewall config
  if [ "${SYNOPKG_PKG_STATUS}" == "UNINSTALL" ]; then
    /usr/syno/bin/servicetool --remove-configure-file --package ${SYNOPKG_PKGNAME}.sc > /dev/null
  fi
  
  #remove daemon user's home directory (needed since DSM 4.1)
  [ -e /var/services/homes/${DAEMON_USER} ] && rm -r /var/services/homes/${DAEMON_USER}
  
  exit 0
}
 

start-stop-status.sh

#!/bin/sh

#--------OPENREMOTE start-stop-status script
#--------package maintained at pcloadletter.co.uk

DNAME="`dirname $0 | cut -f4 -d'/'`"
DAEMON_USER="`echo ${DNAME} | awk {'print tolower($_)'}`"
DAEMON_ID="${DNAME} daemon user"
DAEMON_HOME="`cat /etc/passwd | grep "${DAEMON_ID}" | cut -f6 -d':'`"
PKG_FOLDER="`dirname $0 | cut -f1-4 -d'/'`"
#DLOG="${PKG_FOLDER}/target/logs/catalina.out"
DLOG="${PKG_FOLDER}/target/logs/container/stderrout.log"
PID_FILE="${PKG_FOLDER}/target/${DNAME}.pid"
ENGINE_SCRIPT="openremote.sh"
TIMESTAMP="`date "+%F %X,000"`"
source /etc/profile
source /root/.profile


start_daemon ()
{
  #set the current timezone for Java so that log timestamps are accurate, modern timezone names so DST works
  SYNO_TZ=`cat /etc/synoinfo.conf | grep timezone | cut -f2 -d'"'`
  #fix for DST time in DSM 5.2 thanks to MinimServer Syno package author
  [ -e /usr/share/zoneinfo/Timezone/synotztable.json ] \
   && SYNO_TZ=`jq ".${SYNO_TZ} | .nameInTZDB" /usr/share/zoneinfo/Timezone/synotztable.json | sed -e "s/\"//g"` \
   || SYNO_TZ=`grep "^${SYNO_TZ}" /usr/share/zoneinfo/Timezone/tzname | sed -e "s/^.*= //"`
  grep "^export TZ" ${DAEMON_HOME}/.profile > /dev/null \
   && sed -i "s%^export TZ=.*$%export TZ='${SYNO_TZ}'%" ${DAEMON_HOME}/.profile \
   || echo export TZ=\'${SYNO_TZ}\' >> ${DAEMON_HOME}/.profile
  
  su - ${DAEMON_USER} -s /bin/sh -c "cd ${PKG_FOLDER}/target/bin && source ~/.profile && ./${ENGINE_SCRIPT} start"
  if [ -z ${SYNOPKG_PKGDEST} ]; then
    #script was manually invoked, need this to show status change in Package Center
    [ -e ${PKG_FOLDER}/enabled ] || touch ${PKG_FOLDER}/enabled
  fi
}

stop_daemon ()
{
  kill `cat ${PID_FILE}`
  wait_for_status 1 20 || kill -9 `cat ${PID_FILE}`
  rm -f ${PID_FILE}
  if [ -z ${SYNOPKG_PKGDEST} ]; then
    #script was manually invoked, need this to show status change in Package Center
    [ -e ${PKG_FOLDER}/enabled ] && rm ${PKG_FOLDER}/enabled
  fi
}

daemon_status ()
{
  if [ -f ${PID_FILE} ] && kill -0 `cat ${PID_FILE}` > /dev/null 2>&1; then
    return
  fi
  rm -f ${PID_FILE}
  return 1
}

wait_for_status ()
{
  counter=$2
  while [ ${counter} -gt 0 ]; do
    daemon_status
    [ $? -eq $1 ] && return
    let counter=counter-1
    sleep 1
  done
  return 1
}

case $1 in
  start)
    if daemon_status; then
      echo ${DNAME} is already running with PID `cat ${PID_FILE}`
      exit 0
    else
      echo Starting ${DNAME} ...
      start_daemon
      exit $?
    fi
  ;;

  stop)
    if daemon_status; then
      echo Stopping ${DNAME} ...
      stop_daemon
      exit $?
    else
      echo ${DNAME} is not running
      exit 0
    fi
  ;;

  restart)
    stop_daemon
    start_daemon
    exit $?
  ;;

  status)
    if daemon_status; then
      echo ${DNAME} is running with PID `cat ${PID_FILE}`
      exit 0
    else
      echo ${DNAME} is not running
      exit 1
    fi
  ;;

  log)
    echo "${DLOG}"
    exit 0
  ;;

  *)
    echo "Usage: $0 {start|stop|status|restart}" >&2
    exit 1
  ;;

esac
 

Changelog:

  • 2.6.2-0010 25 Jul 2016 – Substantial re-brand and overhaul for DSM 6.0, updated to OpenRemote Controller 2.6.2 beta which adds Java 8 compatibility, Controller is now the Pro version which is free for personal non-commercial use – registration for an OpenRemote Designer account is required, added many enhancements developed for other packages
  • 2.1.1-0009 May 2016 – Abandoned test, never published
  • 2.0.1-0008 23 Jan 2013 – Changes not recorded
  • 2.0.1-0007 20 Jan 2013 – Fixes for DSM 4.2
  • 2.0.1-006 24 Nov 2012 – Updated to release 2.0.1, merged the package scripts for easier maintenance
  • 2.0.0-005 12 Mar 2012 – Updated to release 2.0 with Web Console, package now downloads installation files directly from openremote.org, removed Java 6 check, timezone support for Java, icons vanish from DSM menu when package in stopped state, added URL for Web Console to Package Info in Package Center
  • 2.0.0_20110611-004 18 Nov 2011 – Fixed missing panel.xml error due to relative path problem in openremote.sh, documented on OpenRemote forum
  • 2.0.0_20110611-003 18 Nov 2011 – Fixed controller TCP port after autodiscover from panel
  • 2.0.0_20110611-002 17 Nov 2011 – Updated for package repo to allow update notification, made Java 6 mandatory and added link to user forum in More Info
  • 2.0.0_SNAPSHOT_20110611 25 Oct 2011 – v1 initial spk release
 
 

219 thoughts on “OpenRemote package for Synology NAS

  1. Jim

    Just as supplement… the type of simple rules that I am trying to implement :

    package org.openremote.controller.protocol

    global org.openremote.controller.statuscache.CommandFacade execute;
    global org.openremote.controller.statuscache.SwitchFacade switches;

    rule “Lights off at 22:45”

    timer (cron: 0 34 22 * * ?) when eval (true) then

    execute.command(“Cuisine PLRC03 On-Off (ON)”);

    end

    Reply
  2. Michael

    Hi Patters, thank you for your work on this. I am not sure if it’s due to the newer version of the link to Git hub but the link in installer.sh doesnt seem to work. I am wondering if this is impacting pn my panel xml not found issue. I have followed the instructions perfectly in your instructions above but with no luck? any ideas? Thanks Mike.

    Reply

Leave a comment