Script: Using a Nest to control a slave electric heater

Moderator: leecollings

Post Reply
bobMuk
Posts: 6
Joined: Saturday 19 November 2016 16:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Script: Using a Nest to control a slave electric heater

Post by bobMuk »

I've been coming to this forum for help for a while now, so thought I'd try and give something back - below is a simple bash script that can be run from /etc/rc.local which allows you to control an electric heater in a room which isn't part of the central heating system (mine is in my attic) using your Nest. The Nest provides the setpoints and the script turns the heater on/off as required.

Requires a Nest thermostat, a wireless thermometer and a Domoticz-controllable plug/socket for your heater.
The user constants should be self explanatory...

Caveats:
1) Your electric heater needs to be powerful enough - eg. if your Nest switches to 20deg at 6:15 in order to get the main house upto temperature by 7:00 and your heater isn't very powerful then the room may not reach 20deg by 7:00.
2)You can override the setpoint at any time by creating a file /tmp/HEATER_OVERRIDE containing the new setpoint (must be one decimal place, eg. 20.5). I added this as a workaround for (1) until I buy a more powerful heater :)
3) default behaviour is if the thermostat has stopped transmitting then we turn off the heater and wait until it's back. This beahviour may not suit everyone.
4) the check_temp_sensor function is a standalone script on my system (it's used for other things too); I've added it as a function to the script without testing but it should just work.

Hope somebody finds this useful :)

Code: Select all

#!/bin/bash
#version 2 - uses the nest setpoint and relies on the master switch being on
#a timer to determine when it's running. Does not heat when nest is in away mode

###################################################################################
###################################################################################
#user constants

#domoticz login
muser="XXXX"
mpass="XXXX"

#masterswitch - dummy switch in domoticz, switches off heater and pauses this script when set to Off
maswitch=157

#thermometer device ID in domoticz
thermdev=153

#heater device ID
heaterid=65

#nest temperature setpoint device id
nestpoint=15

#nest away device id
nestdev=17

#honour nest away - 1 for keep running with the nest away temperature setting,
#0 for shutdown heater and pause until nest says home
honournestaway=0

###################################################################################
###################################################################################

function check_temp_sensor {
#args: <deviceID> [allowed age]

failrc=1

if [ $# -ne 1 ] && [ $# -ne 2 ]
then
        exit $failrc
fi

if [ $# -eq 2 ]
then
        allowedage=$2
else
        allowedage=3600
fi

returnme=UNTRUSTED
wget "http://$muser:$mpass@localhost/json.htm?type=devices&rid=$1" -q -O /tmp/tempscript.out 2> /dev/null > /dev/null
if [ $? -eq 0 ]
then
        therval=`cat /tmp/tempscript.out | grep  "\"Data\"" | sed -e "s/^.*: \"//" -e "s/ .*//"`
        lastupdate=`cat /tmp/tempscript.out | grep  "\"LastUpdate\"" | sed -e "s/^.*: \"//" -e "s/\",$//"`
        updateepoch=`date --date="$lastupdate" +%s`
        interval=$((`date +%s` - $updateepoch))
        if [ $interval -lt $allowedage ]
        then
                returnme=$therval
                failrc=0
        fi
fi

echo $returnme
exit $failrc
}

function getswstatus {
        wget "http://$muser:$mpass@localhost/json.htm?type=devices&rid=$1" -q -O - 2> /dev/null | grep  "\"Status\"" | sed -e "s/^.*: \"//" -e "s/\",//"
}

function setswitch {
        #args devID On/Off
        wget "http://$muser:$mpass@localhost/json.htm?type=command&param=switchlight&idx=$1&switchcmd=$2" -q -O - 2> /dev/null > /dev/null
        #resend command after 7s to make sure it gets through
        sleep 7
        wget "http://$muser:$mpass@localhost/json.htm?type=command&param=switchlight&idx=$1&switchcmd=$2" -q -O - 2> /dev/null > /dev/null
        #always sleep 40s after switching to avoid rapid on/off
        sleep 40
}

#get initial state of heater
if [ "`getswstatus $heaterid`" == "On" ]
then
        currentstate=1
else
        currentstate=0
fi
sleepintervals=300
setvar=0
prev1temp=0
onoverride=0


echo "======================================="
echo "`date +"%d%m%y %H:%M"` `echo $0 | sed -e "s/^.*\///"` is starting"
echo "======================================="
echo "`date +"%d%m%y %H:%M"` Initial state HEATER: `echo $currentstate | sed -e "s/1/On/" -e "s/0/Off/"`  NESTAWAY: `getswstatus $nestdev`  HONOURNESTAWAY: `echo $honournestaway | sed -e "s/1/On/" -e "s/0/Off/"`"

while true
do
        if [ "`getswstatus $maswitch`" == "Off" ]
        then
                #explicitly send an off instead of checking where were at so the switch acts as a master shutdown
                #regarless of if someone has been manually changing the heater in domoticz
                currentstate=0
                echo "`date +"%d%m%y %H:%M"` Master switch is off, sleeping"
                setswitch $heaterid Off
                sleep $sleepintervals
                while [ "`getswstatus $maswitch`" == "Off" ]
                do
                        sleep $sleepintervals
                done
                echo "`date +"%d%m%y %H:%M"` Master switch is back ON, resuming"
        fi

        #chose to shutdown the heat and wait if nest in away mode, or carry
        #on with heating using the nest-away temperature
        if [ $honournestaway -eq 0 ]
        then
                if [ "`getswstatus $nestdev`" == "On" ]
                then
                        echo -n "`date +"%d%m%y %H:%M"` Detected Nest Away mode - "
                        #shut everything down until nestaway is Off
                        if [ $currentstate -eq 1 ]
                        then
                                echo -n "shutting down heater and "
                                currentstate=0
                                #send off command
                                setswitch $heaterid Off
                        fi
                        echo "sleeping"

                        #sleep and wait until nestaway is Off
                        sleep $sleepintervals
                        while [ "`getswstatus $nestdev`" == "On" ]
                        do
                                sleep $sleepintervals
                        done
                        echo "`date +"%d%m%y %H:%M"` Detected Nest Home mode - resuming"
                fi
        fi


        oldsetvar=$setvar
        if [ -r /tmp/HEATER_OVERRIDE ]
        then
                setpoint=`cat /tmp/HEATER_OVERRIDE`
                onoverride=1
        else
                setpoint=`wget "http://$muser:$mpass@localhost/json.htm?type=devices&rid=$nestpoint" -q -O - 2> /dev/null | grep  "^ *\"SetPoint\"" | sed -e "s/^.*: \"//" -e "s/\",//"`
                if [ $onoverride -eq 1 ]
                then
                        echo "`date +"%d%m%y %H:%M"` OVERRIDE removed, going back to Nest setpoint"
                        onoverride=0
                fi
        fi
        setvar=`echo $setpoint | sed -e "s/\.//"`
        if [ $setvar -ne $oldsetvar ]
        then
                if [ $onoverride -eq 1 ]
                then
                        echo "`date +"%d%m%y %H:%M"` OVERRIDE Setpoint set to $setpoint"
                else
                        echo "`date +"%d%m%y %H:%M"` Setpoint set to $setpoint"
                fi
        fi
        currtemp=`/home/pi/check_temp_sensor $thermdev 1800`
        if [ "$currtemp" != "UNTRUSTED" ]
        then
                if [ "`echo $currtemp | sed -e 's/\.//'`" -lt $setvar ]
                then
                        if [ $currentstate -eq 0 ]
                        then
                                echo "`date +"%d%m%y %H:%M"` under temp, switching ON - setpoint $setpoint currenttemp $currtemp"
                                currentstate=1
                                #send on command
                                setswitch $heaterid On
                                prev1temp=$currtemp
                                onitercount=0
                        fi
                else
                        if [ $currentstate -eq 1 ]
                        then
                                echo "`date +"%d%m%y %H:%M"` over temp, switching off - setpoint $setpoint currenttemp $currtemp"
                                currentstate=0
                                #send off command
                                setswitch $heaterid Off
                        fi

                fi
        else
                #untrusted thermometer - shutdown?
                if [ $currentstate -eq 1 ]
                then
                        echo "`date +"%d%m%y %H:%M"` UNTRUSTED thermometer - shutting down heater until it recovers"
                        currentstate=0
                        #send off command
                        setswitch $heaterid Off
                        while [ "`/home/pi/check_temp_sensor $thermdev 1800`" == "UNTRUSTED" ]
                        do
                                sleep $sleepintervals
                        done
                        echo "`date +"%d%m%y %H:%M"` thermometer is now transmitting, resuming"
                fi
        fi

        sleep $sleepintervals


        #check state var reflects reality
        if [ "`getswstatus $heaterid`" == "On" ]
        then
                if [ $currentstate -eq 0 ]
                then
                        echo "`date +"%d%m%y %H:%M"` Heater unexpectedly ON in Domoticz, switching off"
                        setswitch $heaterid Off
                fi
        else
                if [ $currentstate -eq 1 ]
                then
                        echo "`date +"%d%m%y %H:%M"` Heater unexpectedly OFF in Domoticz, switching on"
                        setswitch $heaterid On
                fi
        fi
done
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest