NEST en Google

Spijtig genoeg is NEST overgenomen door Google en dus is de API en NEST integratie op zijn laatste pootjes aan het draaien.

Het officiële bericht hierover was:
Works with Nest API deprecation date. Nest device APIs will be turned off August 31, 2019. 

U kan dus de NEST integratie zoals die hier op de site beschreven staat niet meer gebruiken. Wel prijkt de mooie tekst op de site dat je uw NEST nu met een Google Assistant kan koppelen ! Alsof ik daar op zat te wachten…

NEST instellen en uitlezen

! LET OP ! LEES EERST: !

NEST en Google

Vanaf dat je een werkend NEST device hebt is het heel simpel om in LUA de instellingen van je thermostaat uit te lezen of een nieuw setpoint in te stellen.

Om de ingestelde setpoint, de huidige gemeten temperatuur en vochtigheid uit te lezen gebruik je volgende code:

(bij nestDevice moet je de 0 vervangen door het ID van je Virtual Device)

local nestDevice=0  --id of the Nest Virtual Device

  local setpoint=tonumber(fibaro:getValue(nestDevice,"ui.settemp.value"))
  local current_temperature=tonumber(fibaro:getValue(nestDevice,"ui.curtemp.value"))  
  local humidity=tonumber(fibaro:getValue(nestDevice,"ui.curhum.value"))

Om de setpoint te veranderen gebruik je volgende code:

local nestDevice=0 --id of the Nest Virtual Device

  fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", 20)
-- replace 20 by the required value

Vergeet niet dat het 5 minuten kan duren vooraleer je NEST thermostaat ook de gewenste waarde weergeeft.

Nest Device en Scene v2

! LET OP ! LEES EERST: !

NEST en Google

Aangezien een gebruiker mij de opmerking gaf dat manuele aanpassingen aan de thermostaat altijd overschreven werden door de Fibaro programmatie, en dat in zijn geval niet wenselijk was, heb ik een 2e versie gemaakt van het device en de scene. Nu kan je perfect de twee combineren. Manuele aanpassingen hebben voorrang op de geprogrammeerde instelling, tot de volgende programmeerstap eraan komt, en dan gaat hij verder met de geprogrammeerde temperatuur.

Zie ook het grafiekje hieronder:

img099

Voor de download van het tt_nestdevicev2

Na versie 4.110 heb je de nieuwe nodig: tt_nestdevicev3

Ondertussen al 1 klein bugje ontdekt… in het virtueel Device staat de start-url als “https://developer-api.nest.com” ; dit moet echter “https://developer-api.nest.com/” zijn.
Dit kan je rechtzetten in de code van het virtueel device en met het aanmaken van een knop die : “fibaro:call(NestButtonId,”setProperty”,”ui.url.value”,”https://developer-api.nest.com/”)” doet en deze dan uit te voeren.

Voor de code v2 van de Scene:

update – 13/3: versie 2.1

--[[
%% properties
%% events
%% globals
--]]
local NestButton=

local setpincode=fibaro:getValue(NestButton,"ui.pincode.value")
local acccode=fibaro:getValue(NestButton,"ui.acccode.value")
local thermoid=fibaro:getValue(NestButton,"ui.thermoid.value")
local uri=fibaro:getValue(NestButton,"ui.url.value")

function capture307(status)
      if (tonumber(status.status)==307) then
      	fibaro:call(NestButton, "setProperty","ui.url.value","https://"..status.headers.Location:match('^%w+://([^/]+)').."/")
    	fibaro:debug("307 Status - URL cached ".."https://"..status.headers.Location:match('^%w+://([^/]+)').."/")
      else     
        result = json.decode(status.data)
        if (result~=nil) then
          --fibaro:debug("200 Result - returning")
        else
          fibaro:debug("200 Result - nil response")
        end
        return result
      end
end

function doRequest(url,options)
  local selfhttp = net.HTTPClient({timeout=2000}) 
  selfhttp:request(url,options)
end

--have pincode, not acccode; get acccode
if (acccode=="") then
  if (setpincode~="") then
    fibaro:call(NestButton,"setProperty","ui.log.value",'access code request')
    fibaro:debug('running access code request')
    local body="code="..setpincode.."&client_id=85678ff8-99b5-47e5-b3fb-320dce57b9e6&client_secret=obH3q6WhTpzkdI5mL3zqRq3VT&grant_type=authorization_code"
	--fibaro:debug(body)
    doRequest("https://api.home.nest.com/oauth2/access_token?"..body,{ 
      options={
		method = 'POST', 
		timeout = 5000
		}, 
      	success=function(status)
          	fibaro:debug("Received Access Code")
        	result=capture307(status)
         	fibaro:call(NestButton,"setProperty","ui.acccode.value","Bearer "..result['access_token'])
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  end
  fibaro:sleep(1100)
end
-- have acccode not thermoid; get thermostat id
if (acccode~="") and (thermoid=="") then
  fibaro:call(NestButton,"setProperty","ui.log.value",'thermostat id request')
  doRequest(uri.."devices/thermostats",{ 
      options={
        headers = {
          	['Content-Type'] = "application/json",
            ['Authorization'] = acccode
        }, 
		method = 'GET', 
		timeout = 5000
	  }, 
      success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
        		local tid=""
        		for k in pairs(result) do
        			tid=k
        		end
         		fibaro:call(NestButton,"setProperty","ui.thermoid.value",tid)
         		fibaro:call(NestButton,"setProperty","ui.setpoint.value","-1")
         		fibaro:call(NestButton,"setProperty","ui.oldsetp.value","-1")
         		fibaro:call(NestButton,"setProperty","ui.oldtosetp.value","-1")
          		fibaro:debug("Received Thermostat ID")
          	end
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  fibaro:sleep(1100)
end

-- have accode and thermoid
if (acccode~="") and (thermoid~="") then
    fibaro:call(NestButton,"setProperty","ui.log.value",'data update request')
	doRequest(uri.."devices/thermostats/"..thermoid,{ 
      options={
        headers = {
          	['Content-Type'] = "application/json",
            ['Authorization'] = acccode
        }, 
		method = 'GET', 
		timeout = 5000
	  }, 
      success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
          		fibaro:debug("Received Thermostat Data")
          		if (result["temperature_scale"]=="C") then
            		fibaro:call(NestButton,"setProperty","ui.scale.value","°C")
            		fibaro:call(NestButton,"setProperty","ui.curtemp.value",result["ambient_temperature_c"])
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_c"])
            		local sp=fibaro:getValue(NestButton,"ui.setpoint.value")
            		if (tonumber(sp)==-1) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_c"])
              			fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_c"])
              			fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_c"])
              		end
				  	local ocsp=tonumber(fibaro:getValue(NestButton,"ui.oldsetp.value"))
					-- (ocsp<>csp) => manual change, overrule tsp change => ocsp:=csp & otsp:=csp & tsp:=csp
            		if (ocsp~=tonumber(result["target_temperature_c"])) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_c"])
              			fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_c"])
              			fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_c"])
              		end
          		else
            		fibaro:call(NestButton,"setProperty","ui.scale.Label","°F")
            		fibaro:call(NestButton,"setProperty","ui.curtemp.value",result["ambient_temperature_f"])
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_f"])
            		local sp=fibaro:getValue(NestButton,"ui.setpoint.value")
            		if (tonumber(sp)==-1) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_f"])
              			fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_f"])
              			fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_f"])
              		end
				  	local ocsp=tonumber(fibaro:getValue(NestButton,"ui.oldsetp.value"))
					-- (ocsp<>csp) => manual change, overrule tsp change => ocsp:=csp & otsp:=csp & tsp:=csp
            		if (ocsp~=tonumber(result["target_temperature_f"])) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_f"])
              			fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_f"])
              			fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_f"])
              		end
          		end
            	fibaro:call(NestButton,"setProperty","ui.curhum.value",result["humidity"])
            	fibaro:call(NestButton,"setProperty","ui.online.value",result["is_online"])
          	end
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  fibaro:sleep(1100)
end

--have all, setpoint initialised
if (acccode~="") and (thermoid~="") and (tonumber(fibaro:getValue(NestButton,"ui.setpoint.value"))~=-1) then
    fibaro:call(NestButton,"setProperty","ui.log.value",'checking setpoint')
  	local csp=tonumber(fibaro:getValue(NestButton,"ui.settemp.value"))
  	local ocsp=tonumber(fibaro:getValue(NestButton,"ui.oldsetp.value"))
  	local tsp=tonumber(fibaro:getValue(NestButton,"ui.setpoint.value"))
  	local otsp=tonumber(fibaro:getValue(NestButton,"ui.oldtosetp.value"))
	-- (otsp<>tsp) => prog change (and update ness) => 
	--      => otsp:=tsp & PUT tsp + success = csp:=tsp & ocsp=tsp & otsp=tsp
  	if (otsp~=tsp) then
    	local pmsg=""
    	fibaro:debug("SetTempFrom : "..csp.." To: "..tsp)
    	if (fibaro:getValue(NestButton,"ui.scale.value")=="°C") then
    		pmsg='{"target_temperature_c": '..tsp..'}'
      	else
    		pmsg='{"target_temperature_f": '..tsp..'}'
      	end
    	fibaro:call(NestButton,"setProperty","ui.log.value",'changing setpoint from '..csp.." to "..tsp)
		doRequest(uri.."devices/thermostats/"..thermoid,{ 
    	  options={
        	headers = {
          		['Content-Type'] = "application/json",
            	['Authorization'] = acccode
        	}, 
			method = 'PUT', 
          	data = pmsg,
			timeout = 5000
	  	}, 
      	success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
          		fibaro:debug("Temperature Set OK")
          		if (result["target_temperature_c"]~=nil) then
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_c"])
            		fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_c"])
            		fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_c"])
          		end
          		if (result["target_temperature_f"]~=nil) then
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_f"])
            		fibaro:call(NestButton,"setProperty","ui.oldsetp.value",result["target_temperature_f"])
            		fibaro:call(NestButton,"setProperty","ui.oldtosetp.value",result["target_temperature_f"])
          		end
          	end
        end,
      error = function(status)
            fibaro:debug("error "..status)
            if (status=="Connection refused") then
                fibaro:call(NestButton,"setProperty","ui.url.value","https://developer-api.nest.com/")
                 fibaro:debug("Resetting Nest URL")
            end
      end
       })
    end
  fibaro:sleep(1100)
end

NEST API toegang v1

! LET OP ! LEES EERST: !

NEST en Google

Als het allemaal goed gelukt is, heb je in je Fibaro Home Center 2 nu:

  • 1 virtueel device
  • 1 scene

voor je NEST en heb je in het virtueel device het id van de scene getypt en omgekeerd.

Rest je nog 1 ding te doen en dat is deze twee te laten praten met de NEST API. Hiervoor moet je zelf de toestemming geven en aan de Fibaro laten weten dat je de toestemming gekregen hebt van NEST. Dit gaat als volgt:

  • je klikt op deze officiële NEST link, en een nieuwe pagina gaat open in je browser
  • indien je nog niet aangemeld was op je eigen NEST account, moet je dat nu doen
  • NEST toont je een pagina waar je de goedkeuring moet geven dat de Fibaro de temperatuurinstelling van je thermostaat mag wijzigen
  • Als je akkoord bent gegaan krijg je een pagina te zien met een PINCODE op. Noteer deze nu ! Deze is slechts één keer geldig.

Wanneer je de PINCODE hebt, moet je die nog in je Fibaro kenbaar maken. Dit doe je door naar “Devices” te gaan en je virtueel NEST device te kiezen. Daar ga je naar de tab “Advanced” en bij de LUA van de eerste knop zoek je:

local pincode="" --fill in your licensed PIN CODE

Hier vul je tussen de aanhalingstekens je PINCODE in. Vervolgens druk je op “Save” (het icoontje rechts van je scherm met een antieke diskette op) en in het volgende scherm druk je op de knop “GET/SET PIN”.

Nu zou de pincode zichtbaar moeten worden in het Virtual Device en moet je een 15-tal minuten wachten. Na die 15 minuten zou het Device geïnitialiseerd moeten zijn en moet je de instellingen van je thermostaat kunnen zien.

Zie verder met LUA instellen en uitlezen.

Vermits ik heel wat tijd en effort gestoken heb in deze integratie zou ik nogmaals willen vragen om echt te overwegen om een donatie te maken via Paypal (met de knop links) indien je deze code gebruikt.

NEST Scene v1

! LET OP ! LEES EERST: !

NEST en Google

Maak in je Fibaro HC2 een nieuwe Scene aan in LUA. Zet in de “General” tab het maximum aantal simultane processen voor deze scene op “1”. In de Advanced tab voeg je volgende code in:

--[[
%% properties
%% events
%% globals
--]]
local NestButton=0 --id of the virtual device

local setpincode=fibaro:getValue(NestButton,"ui.pincode.value")
local acccode=fibaro:getValue(NestButton,"ui.acccode.value")
local thermoid=fibaro:getValue(NestButton,"ui.thermoid.value")
local uri=fibaro:getValue(NestButton,"ui.url.value")

function capture307(status)
      if (tonumber(status.status)==307) then
      	fibaro:call(NestButton, "setProperty","ui.url.value","https://"..status.headers.Location:match('^%w+://([^/]+)').."/")
    	fibaro:debug("307 Status - URL cached ".."https://"..status.headers.Location:match('^%w+://([^/]+)').."/")
      else     
        result = json.decode(status.data)
        if (result~=nil) then
          --fibaro:debug("200 Result - returning")
        else
          fibaro:debug("200 Result - nil response")
        end
        return result
      end
end

function doRequest(url,options)
  local selfhttp = net.HTTPClient({timeout=2000}) 
  selfhttp:request(url,options)
end

--have pincode, not acccode; get acccode
if (acccode=="") then
  if (setpincode~="") then
    fibaro:call(NestButton,"setProperty","ui.log.value",'access code request')
    fibaro:debug('running access code request')
    local body="code="..setpincode.."&client_id=85678ff8-99b5-47e5-b3fb-320dce57b9e6&client_secret=obH3q6WhTpzkdI5mL3zqRq3VT&grant_type=authorization_code"
	--fibaro:debug(body)
    doRequest("https://api.home.nest.com/oauth2/access_token?"..body,{ 
      options={
		method = 'POST', 
		timeout = 5000
		}, 
      	success=function(status)
          	fibaro:debug("Received Access Code")
        	result=capture307(status)
         	fibaro:call(NestButton,"setProperty","ui.acccode.value","Bearer "..result['access_token'])
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  end
  fibaro:sleep(1100)
end
-- have acccode not thermoid; get thermostat id
if (acccode~="") and (thermoid=="") then
  fibaro:call(NestButton,"setProperty","ui.log.value",'thermostat id request')
  doRequest(uri.."devices/thermostats",{ 
      options={
        headers = {
          	['Content-Type'] = "application/json",
            ['Authorization'] = acccode
        }, 
		method = 'GET', 
		timeout = 5000
	  }, 
      success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
        		local tid=""
        		for k in pairs(result) do
        			tid=k
        		end
         		fibaro:call(NestButton,"setProperty","ui.thermoid.value",tid)
         		fibaro:call(NestButton,"setProperty","ui.setpoint.value","-1")
          		fibaro:debug("Received Thermostat ID")
          	end
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  fibaro:sleep(1100)
end

-- have accode and thermoid
if (acccode~="") and (thermoid~="") then
    fibaro:call(NestButton,"setProperty","ui.log.value",'data update request')
	doRequest(uri.."devices/thermostats/"..thermoid,{ 
      options={
        headers = {
          	['Content-Type'] = "application/json",
            ['Authorization'] = acccode
        }, 
		method = 'GET', 
		timeout = 5000
	  }, 
      success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
          		fibaro:debug("Received Thermostat Data")
          		if (result["temperature_scale"]=="C") then
            		fibaro:call(NestButton,"setProperty","ui.scale.value","°C")
            		fibaro:call(NestButton,"setProperty","ui.curtemp.value",result["ambient_temperature_c"])
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_c"])
            		local sp=fibaro:getValue(NestButton,"ui.setpoint.value")
            		if (tonumber(sp)==-1) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_c"])
              		end
          		else
            		fibaro:call(NestButton,"setProperty","ui.scale.Label","°F")
            		fibaro:call(NestButton,"setProperty","ui.curtemp.value",result["ambient_temperature_f"])
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_f"])
            		local sp=fibaro:getValue(NestButton,"ui.setpoint.value")
            		if (tonumber(sp)==-1) then
              			fibaro:call(NestButton,"setProperty","ui.setpoint.value",result["target_temperature_c"])
              		end
          		end
            	fibaro:call(NestButton,"setProperty","ui.curhum.value",result["humidity"])
            	fibaro:call(NestButton,"setProperty","ui.online.value",result["is_online"])
          	end
        end,
      error = function(status)
        	fibaro:debug("error "..status)
      end
       })
  fibaro:sleep(1100)
end

--have all, setpoint different from requested
if (acccode~="") and (thermoid~="") and (tonumber(fibaro:getValue(NestButton,"ui.setpoint.value"))~=-1) then
    fibaro:call(NestButton,"setProperty","ui.log.value",'checking setpoint')
  	local csp=fibaro:getValue(NestButton,"ui.settemp.value")
  	local tsp=fibaro:getValue(NestButton,"ui.setpoint.value")
  	if (tonumber(csp)~=tonumber(tsp)) then
    	local pmsg=""
    	fibaro:debug("SetTempFrom : "..csp.." To: "..tsp)
    	if (fibaro:getValue(NestButton,"ui.scale.value")=="°C") then
    		pmsg='{"target_temperature_c": '..tsp..'}'
      	else
    		pmsg='{"target_temperature_f": '..tsp..'}'
      	end
    	fibaro:call(NestButton,"setProperty","ui.log.value",'changing setpoint from '..csp.." to "..tsp)
		doRequest(uri.."devices/thermostats/"..thermoid,{ 
    	  options={
        	headers = {
          		['Content-Type'] = "application/json",
            	['Authorization'] = acccode
        	}, 
			method = 'PUT', 
          	data = pmsg,
			timeout = 5000
	  	}, 
      	success=function(status)
        	local result=capture307(status)
        	if (result~=nil) then
          		fibaro:debug("Temperature Set OK")
          		if (result["target_temperature_c"]~=nil) then
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_c"])
          		end
          		if (result["target_temperature_f"]~=nil) then
            		fibaro:call(NestButton,"setProperty","ui.settemp.value",result["target_temperature_f"])
          		end
          	end
        end
       })
    end
  fibaro:sleep(1100)
end

Sla deze scene op en onthou het ID dat toegekend wordt aan de scene. Dit kan je aflezen bovenaan in de balk van je internet browser (…/fibaro/en/scenes/edit.html?id=59)  => 59

Ga vervolgens verder met het aanmaken van het virtual device.

NEST Device v1

Download het bestand via de volgende link:

Nest Device

Ga in de Fibaro HC2 naar “Devices” en klik op “Import Device”; selecteer vervolgens het gedownloade bestand.

In de balk van je browser zie je vervolgens het ID van je Virtual Device. Noteer dit ergens.

Ga naar de “Advanced” Tab van het virtuele device. Helemaal onderaan in de “Main Loop” waar staat:

local NestScene=0

vervang je de 0 door het ID van de Scene die je aangemaakt hebt in de vorige stap.

Ga vervolgens terug naar de Scene – “Advanced” tab en daar waar staat:

local NestButton=0

vervang je de 0 door het ID van het Virtual Device dat je gemaakt hebt.

Nog 1 ding te doen en dat is je Pincode verkrijgen voor het gebruik van de API. Zie volgende stap.

NEST, Fibaro en LUA

! LET OP ! LEES EERST: !

NEST en Google

In mijn verwarmingsopstelling heb ik ervoor gekozen om de centrale “domme” “manuele” thermostaat te vervangen door een model dat ik via de Fibaro Home Center 2 kan aansturen. Na wat opzoekwerk heb ik toch gekozen voor de NEST Thermostaat. Wel prijzig, maar ziet er knap uit, ondersteunt zowel het “Aan-Uit” protocol als het modernere “OpenTherm” protocol voor nieuwere ketels. Verder is hij ook draadloos verbonden met de ketel (via de bijgeleverde “Heatlink” module) zodat je geen sturingskabel meer nodig hebt tussen de kamerthermostaat en de ketel en je hem dus overal in je huis kan hangen. Hieronder een schetsje.

img095

De NEST is eigenlijk een “intelligente” thermostaat. Hij kan aanleren hoe je de verwarming instelt, en op basis daarvan een weekschema opmaken dat hij dan automatisch gaat toepassen. In mijn opstelling wil ik deze “intelligente” functionaliteit echter vermijden; ik zal zelf wel iets intelligent ineen steken, aangestuurd door mijn Fibaro Home Center 2. Dit kan, alleen moet je de NEST zijn “intelligentere” functies dan uitzetten.

De NEST heeft een permanente internetverbinding (wireless) nodig om te functioneren, en dan kan je op “http://home.nest.com” een account aanmaken en inloggen en de instellingen aanpassen.

Voor mijn opstelling moet je de volgende instellingen uitzetten:

2016-10-10-13_51_46-eetkamer-nest 2016-10-10-13_52_50-eetkamer-nest2

NEST ondersteunt een heel goede API, met een veilig protocol om in te loggen. Deze zijn echter gebaseerd op HTTPS en Fibaro Virtuele Devices ondersteunen alleen HTTP. Je kan wel HTTPS praten in een Fibaro Scene.

De Fibaro plugin voor NEST thermostaten is bijzonder ontoereikend en functioneert ook niet goed. Spijtig genoeg heeft Fibaro op dit moment de mogelijkheid voor gebruikers om eigen plugins te maken uit gezet. Je zal dus wat moeten typen en prutsen om het werkend te krijgen. In de verder pagina’s zet ik uiteen hoe je het geheel aan de praat krijgt met het aanmaken van 1 virtueel device en 1 scene.

De NEST Scene

Het NEST Virtueel Device

EDIT:

NEST Device en Scene Versie 2 ! Nu met de mogelijkheid om manuele aanpassingen te combineren met geprogrammeerde stappen.

Toegang tot de NEST API

Instellen van het SetPoint en de temperatuur en vochtigheid uitlezen

Vermits ik heel wat tijd en effort gestoken heb in deze integratie zou ik willen vragen om een donatie te maken via Paypal (met de knop links) indien je deze code gebruikt.

Aansturing van de ketel

Om de ketel intelligent aan en uit te schakelen heb je de volgende code nodig:

--[[
%% properties
%% autostart
%% events
%% globals
--]]

local heatsetids={30,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48}
-- de id's van alle set-scenes van de Danfoss Radiatorkoppen
local nestDevice=196
local ketelHeating=0

while true do
  fibaro:debug("Running scene at: "..os.date())
  local setp=tonumber(fibaro:getValue(nestDevice,"ui.settemp.value"))
  local curlivtmp=tonumber(fibaro:getValue(nestDevice,"ui.curtemp.value"))  
  fibaro:debug("SetPoint: "..setp.."  -  Current: "..curlivtmp)
  if (setp>curlivtmp) then
    ketelHeating=1
  else
    ketelHeating=0
  end
  fibaro:setGlobal("G_KetelWarmte",0)
  for i=1,#heatsetids do
    fibaro:startScene(heatsetids[i])
  end
  fibaro:sleep(10*1000)
  if (tonumber(fibaro:getGlobalValue("G_KetelWarmte"))==1) then
    fibaro:debug("Outcome: G_Ketelwarmte=1")
    if (ketelHeating==1) then
      if (setp>curlivtmp) then
        fibaro:debug("Boiler Heat requested - boiler still active")
      else
        fibaro:debug("Boiler Heat requested - boiler still active - updating temp")
	    fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp+1)
      end  
    else
      fibaro:call(nestDevice,"setProperty", "ui.setpoint.value", curlivtmp+1)
      fibaro:debug("Boiler Heat requested - Activating boiler setting temp to: "..curlivtmp+1)
      fibaro:sleep(100)
    end
  else
    fibaro:debug("Outcome: G_Ketelwarmte=0")
    if (ketelHeating==0) then
      if (setp

 

Sturing van de radiatoren

Zie ook de specifieke pagina over Verwarming Sturingen

Schermafdruk 2016-03-16 14.12.43Nu mijn radiatoren uitgerust zijn met de Danfoss LC-13, moeten deze ook aangestuurd worden door de Home Center 2. Eerst heb ik de standaard functionaliteit van de Home Center 2 (het “Heating Panel”) bekeken, maar naar mijn gevoel is dit toch te beperkend of te ingewikkeld om aan te passen naar mijn wens.

De bedoeling was om per kamer de aansturing van de thermostatische radiatorkop op de verwarming te laten afhangen van een aantal globale omgevingsvariabelen en sensorwaarden. Het concept dat ik hierrond bedacht heb gaat uit van

  • een (scene) regeling per kamer, die de juiste temperatuurinstelling van de kop bepaalt, afhankelijk van die variabelen en sensoren die daar nodig zijn, en die instelling doorstuurt naar het device indien nodig
  • een centrale scene die om de 10 minuten alle verschillende kamer-regelingen aanroept om indien nodig de instellingen aan te passen. Verder wordt deze ook geactiveerd door veranderingen in de (globale) variabelen

De centrale scene

Deze ziet er als volgt uit: (in basisversie)

--[[
%% autostart
%% properties
%% events
%% globals
--]]

local heatsetids={30}

while true do
  fibaro:debug("Running scene at: "..os.date())
  for i=1,#heatsetids do
    fibaro:startScene(heatsetids[i])
  end
  fibaro:sleep(10*60*1000)
end

Een scene per kamer

(hier badkamer)

--[[
%% properties
%% events
%% globals
--]]

local iemandthuis=tonumber(fibaro:getGlobalValue("G_IemandThuis"))
local tempbuiten=tonumber(fibaro:getGlobalValue("G_TempBuiten"))

local heaterid=98 --id van de thermostaatkop
local buitenwarmtemp=16 --temperatuur buiten zonder verwarming
local errortemp=18

--per "soort" een scrn : vanuut,vanminuut,totuur,totminuut,setvalue
-- voor een normale weekdag
local thuisweekdag={
  {0,0,6,0,18},
  {6,1,8,30,21},
  {8,31,15,30,18},
  {15,31,17,00,20},
  {17,01,18,30,21},
  {18,31,23,00,20},
  {23,01,23,59,18}
  }

local thuisweekenddag={
  {0,0,6,0,18},
  {6,1,8,30,21},
  {8,31,17,30,20},
  {17,31,18,30,21},
  {18,31,23,00,20},
  {23,01,23,59,18}
  }

local nietthuis={
  {0,0,17,30,18},
  {17,31,20,30,19},
  {20,31,23,0,20},
  {23,01,23,59,18}
  }

local buitenwarm={
  {0,0,23,59,16}
  }

local parsetemp=nietthuis
local schemaName="nietthuis"

if (tempbuiten>=buitenwarmtemp) then
  parsetemp=buitenwarm
  schemaName="buitenwarm"
elseif (iemandthuis==0) then
  parsetemp=nietthuis
  schemaName="nietthuis"
elseif ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then
  parsetemp=thuisweekdag
  schemaName="thuisweekdag"
else
  parsetemp=thuisweekenddag
  schemaName="thuisweekenddag"
end

fibaro:debug("Selected Schema: "..schemaName)

local time=tonumber(os.date("%H"))*60+tonumber(os.date("%M"))
local setlevel=errortemp
local levelttl=0

for i=1,#parsetemp do
  local mintime=parsetemp[i][1]*60+parsetemp[i][2]
  local maxtime=parsetemp[i][3]*60+parsetemp[i][4]
  if ((time>=mintime) and (time<maxtime)) then
    setlevel=parsetemp[i][5]
    levelttl=(maxtime-time-1)
  end
end

fibaro:debug("Selected Temp: "..setlevel.." for: "..levelttl.." minutes")

local currentlevel=tonumber(fibaro:getValue(heaterid,"value"))
if (currentlevel~=setlevel) then
  fibaro:call(heaterid,"setTargetLevel",setlevel)
  fibaro:call(75, "setProperty", "ui.Label1.value", "HeatSteering")
  fibaro:call(75, "setProperty", "ui.Label2.value", "Updating Heater "..fibaro:getName(heaterid).." Time: "..os.date().." to: "..setlevel)
  fibaro:call(75, "setProperty", "ui.Label3.value", "INFORMATIONAL")
  fibaro:call(75, "pressButton", "3")   
  fibaro:sleep(100)
  fibaro:debug("Current setLevel: "..currentlevel.." new level: "..setlevel)
  fibaro:call(heaterid,"setTime",tonumber(os.time(t))+levelttl*60)
end

Radiator LUA code

Hierbij de code die ik voor elk van de verwarmingen apart heb aangegeven. Per kamer heb je zo een scene nodig om de radiatoren van die kamer juist aan te sturen.

--[[
%% properties
%% events
%% globals
--]]

local heaterid=133 --id of the thermostatic valve
local heaterfloor="gelijkvloers" -- for logging
local heaterroom="living" -- for logginh

local extopen1=56  --id of the external door/window sensor
local extopen2=189  --id of the external door/window sensor
local extopen3=0  --id of the external door/window sensor
local exttemp=196  --id of the external temperature sensor
local extmotion=149  --id of the external motion detector
local extmanplus=37 --id of the external heat switch +1 degrees

local buitenwarmtemp=19 --temperatuur outside with heating off
local errortemp=18

local iemandthuis=tonumber(fibaro:getGlobalValue("G_IemandThuis"))
local tempbuiten=tonumber(fibaro:getGlobalValue("G_TempBuiten"))

--per "soort" een scrn : vanuut,vanminuut,totuur,totminuut,setvalue
-- voor een normale weekdag
local thuisweekdag={
  {0,0,6,0,18},
  {6,1,20,0,20},
  {20,1,22,0,21},
  {22,1,23,0,20},
  {23,1,23,59,18}
  }

local thuisweekenddag={
  {0,0,6,0,18},
  {6,1,23,0,20},
  {23,1,23,59,18}
  }

local nietthuis={
  {0,0,17,0,18},
  {17,1,18,0,19},
  {18,1,19,00,20},
  {19,01,23,59,18}
  }

local buitenwarm={
  {0,0,23,59,16}
  }

local parsetemp=nietthuis
local schemaName="nietthuis"

if (tempbuiten>=buitenwarmtemp) then
  parsetemp=buitenwarm
  schemaName="buitenwarm"
elseif (iemandthuis==0) then
  parsetemp=nietthuis
  schemaName="nietthuis"
elseif ((tonumber(os.date("%w"))~=0) and (tonumber(os.date("%w"))~=6)) then
  parsetemp=thuisweekdag
  schemaName="thuisweekdag"
else
  parsetemp=thuisweekenddag
  schemaName="thuisweekenddag"
end

if (extopen1~=0) then
  if (tonumber(fibaro:getValue(extopen1,"value"))==1) then
    parsetemp=buitenwarm
    schemaName="verluchtingopen"
  end
end
if (extopen2~=0) then
  if (tonumber(fibaro:getValue(extopen2,"value"))==1) then
    parsetemp=buitenwarm
    schemaName="verluchtingopen"
  end
end

fibaro:debug("T ext.:"..tempbuiten.."; Selected Schema: "..schemaName)

local time=tonumber(os.date("%H"))*60+tonumber(os.date("%M"))
local setlevel=errortemp
local levelttl=0
local logtotime="--:--"

for i=1,#parsetemp do
  local mintime=parsetemp[i][1]*60+parsetemp[i][2]
  local maxtime=parsetemp[i][3]*60+parsetemp[i][4]
  if ((time>=mintime) and (timetonumber(fibaro:getValue(exttemp,"ui.curtemp.value"))) then
    fibaro:setGlobal("G_KetelWarmte",1)
    fibaro:debug("Demanding Boiler Heat: "..setlevel.." requested "..fibaro:getValue(exttemp,"ui.curtemp.value").." measured")
  end
end

fibaro:debug("Selected Temp: "..setlevel.." for: "..levelttl.." minutes until "..logtotime)

local currentlevel=tonumber(fibaro:getValue(heaterid,"value"))
if (currentlevel~=setlevel) then
  fibaro:call(heaterid,"setTargetLevel",setlevel)
  fibaro:debug("SETTING - Current setLevel: "..currentlevel.." new level: "..setlevel)
  fibaro:call(heaterid,"setTime",tonumber(os.time(t))+levelttl*60)
end