Howto: Control your Rinnai Hot Water on Demand Heater with Control-R Module

This might be helpful for anyone looking to automate their Rinnai Hot Water on demand heater that has the Control-R WiFi module installed. Rinnai’s wifi integration has been a complete hack from the company for over a year and im happy to finally have some form of a solution to turn recirculation on though OpenHAB.

I do not take credit for this, as i came across some code that gains access to their portal for the necessary commands:

Step 1: Install this on your OH Server: GitHub - explosivo22/rinnaicontrolr: Python interface for the Rinnai Control-R API

Step 2: Edit the following script: /usr/local/lib/python3.6/dist-packages/rinnaicontrolr/

Under the following Line (Line:130):

    def is_heating(self, dev):
        return dev['info']['domestic_combustion'] == 'true'


    def get_inlet_temperature(self, dev):
        return dev['info']['m08_inlet_temperature']

    def get_outlet_temperature(self, dev):
        return dev['info']['m02_outlet_temperature']

    def start_maintenance_retrieval(self, dev):
        self._set_shadow(dev, 'do_maintenance_retrieval', 'true')

This will allow you to get some statistics from your unit if you wish, Inlet water temperature, Outlet water temperature, and query ‘maintenance’ which is required to refresh/pull these values listed.

Once that is done, create the following script in your Openhab/scripts directory:

import sys
from rinnaicontrolr import  RinnaiWaterHeater

rinnai = RinnaiWaterHeater('XXemail@email.comXX', 'XXpasswordXX')

for device in rinnai.get_devices():
    if str(sys.argv[1]) == "settemp": #Set the temperature of hot water heater
         rinnai.set_temperature_setpoint(device, sys.argv[2]) # set the temp for the second arguement value

    if str(sys.argv[1]) == "maint": #Start Maintenance retrieval

    if str(sys.argv[1]) == "recirc": #Enable Recirc followed by duration
         rinnai.start_recirculation(device, sys.argv[2]) # Start Recirc with duration variable in minutes

    if str(sys.argv[1]) == "status": #JSON output of status query
          s = ""
          s = s + "{\n"
          s = s + '"TEMP": "%s",\n' % \
          s = s + '"isHeating": "%s",\n' % \
          s = s + '"isRecirculating": "%s",\n' % \
          s = s + '"inletTemp": "%s",\n' % \
          s = s + '"outletTemp": "%s",\n' % \
          s = s + "}\n"

Create the following files in openhab:


Thing exec:command:rinnai [command="/usr/bin/python3 /etc/openhab/scripts/ status", interval=10, timeout=10]


Group Rinnai

Group gRinnai_Parse_json (Rinnai)

String                H_BM_LDRY_Rinnai_JSON                            "Rinnai JSON: [%s]"  {channel="exec:command:rinnai:output"}

Number                H_BM_LDRY_Rinnai_TEMP                       "Current Temperature   [%s °F]"                             (Rinnai,gRinnai_Parse_json)

Number                H_BM_LDRY_Rinnai_SETTEMP                   "Target Temperature   [%s °F]"                              (Rinnai)

Number                H_BM_LDRY_Rinnai_inletTemp "Rinnai Inlet Temperature [%s °F]]" (Rinnai,gRinnai_Parse_json)

Number                H_BM_LDRY_Rinnai_outletTemp "Rinnai Outet Temperature [%s °F]]" (Rinnai,gRinnai_Parse_json)

String                H_BM_LDRY_Rinnai_isHeating "Rinnai Is Heating [%s]" (Rinnai,gRinnai_Parse_json)

String                H_BM_LDRY_Rinnai_isRecirculating "Rinnai is Recirculating [%s]" (Rinnai,gRinnai_Parse_json)

Switch                H_BM_LDRY_Rinnai_RECIRCULATION "Recirculation" (Rinnai) {ga="WaterHeater",expire="1m, command=OFF"}

Number                H_BM_LDRY_Rinnai_RECIRC_DURATION "How long to run Recirc for [%s min]" (Rinnai,gRinnai_Parse_json)


var Timer tRinnai_Reschedule_Maint = null  

rule "Rinnai: Parse JSON output to individual Items"
   Item H_BM_LDRY_Rinnai_JSON changed
logInfo(filename+".R1", "### Rinnai: Parse JSON output to individual Items ###")
   val String json = (H_BM_LDRY_Rinnai_JSON.state as StringType).toString
   gRinnai_Parse_json.members.forEach [ value |
      var String name ='H_BM_LDRY_Rinnai_','$.')
      value.postUpdate(transform("JSONPATH", name, json).replaceAll('"',''))

rule "Rinnai: Turn Recirculation ON"
   Item H_BM_LDRY_Rinnai_RECIRCULATION changed from OFF to ON
logInfo(filename+".R2", "### Rinnai: Turn Recirculation ON ###")
    executeCommandLine("/usr/bin/python3.6", "/etc/openhab/scripts/", "recirc", H_BM_LDRY_Rinnai_RECIRC_DURATION.state.toString())

rule "Rinnai: When Heater is Running, Gather Maintenance Stats (Inlet/Outlet Temps)"
   Item H_BM_LDRY_Rinnai_isHeating changed from False to True
logInfo(filename+".R3", "### Rinnai: When Heater is Running, Gather Maintenance Stats (Inlet/Outlet Temps) ###")
   if(tRinnai_Reschedule_Maint === null) {
         tRinnai_Reschedule_Maint = createTimer(now.plusSeconds(30), [ |
         if(H_BM_LDRY_Rinnai_isHeating.state == "True") {
            executeCommandLine("/usr/bin/python3.6", "/etc/openhab/scripts/", "maint")
            logInfo(filename+".R", "--> Gathering Maintenace Information and Rescheduling retrieval")
         } else {
            logInfo(filename+".R", "<--Canceling Maintenace Retrieval Timer")
            tRinnai_Reschedule_Maint = null

Hope this helps someone that is looking to acheive the same, If you have any questions just ask!