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…

Zelfbouw Codepaneel

Een doe-het-zelf kit bestaande uit een codepaneel met 5 druppels, een Fibaro binaire sensor en een 12V voeding voor in een stopcontact met een extra kabeltje om dit op het codepaneel en de sensor aan te sluiten.

ad-2000-paneel-met-5-druppels_1

Ik moet zeggen dat het mij qua functionaliteit een beetje tegen viel. Ik had verwacht te kunnen identificeren wie er badge’te en eventueel met een code te kunnen werken van “ik verlaat het huis”. Dit blijkt niet mogelijk te zijn; het enige wat je kan doen is de “deurbel” knop gebruiken voor de “ik verlaat het huis” gebeurtenis, en de druppels al dan niet met een code gebruiken om de “iemand komt binnen” gebeurtenis te registreren. Je weet niet wie, maar wel zit de beveiliging er in dat je zonder de juiste code of zonder een geldige druppel het “alarm” niet kan afzetten.

Het was toch wel een beetje een gepruts om het ding ineen te krijgen.

fibaro-binaire-sensor-fib_fgbs_1De Fibaro binaire sensor toevoegen aan je HC2 is ook weer kinderspel. Gewoon “Devices” – “Add device” – “Add” en vervolgens op de sensor zelf het kleine knopje 3 keer snel achter mekaar indrukken.

2016-02-09 13_21_51-Home Center 2

Je kan best ook hier het icoontje bij gelegenheid aanpassen naar een “Door Sensor”.

Wat je wel nog moet doen is in de HC2 config Parameter “3” veranderen in “0-Normal Open Input” voor een van de twee ingangen.

Het codepaneel zelf is niet zo simpel; als je het in het stopcontact steekt, pinkt het “power” lampje rood. Je moet eerst in “programming mode” gaan door het “*” en dan de programming pin code in te geven die ergens verborgen staat in de handleiding. (en dan volgen 2 beeps)

Om te kiezen voor alleen een druppel, zonder pin code moet je vervolgens op het nummer “1” drukken en dan “0” drukken (2 beeps). Dan moet je al je druppels gaan toevoegen.

Ik heb hiervoor de laatste drie cijfers van de druppel als identificatie genomen (met max 255) en dan gaat het als volgt: programming mode – “5” drukken (2 beeps) – 3 laatste cijfers drukken (2 beeps) – met de druppel badgen (3 beeps). Als de laatste stap niet lukt, gewoon nog eens badgen of opnieuw beginnen.

De rest ziet er wel leuk uit…

In mijn omgeving gebruik ik het codepaneel onder andere om te weten of er iemand thuis is of niet:

Indien iemand thuiskomt en badget met de druppel:

--[[
%% properties
43 value
%% events
%% globals
--]]

if (fibaro:getValue(43, "value")=="0") then
  fibaro:debug("1->0 detected, aanwezigen: "..fibaro:getGlobalValue("G_IemandThuis"))
  fibaro:setGlobal("G_IemandThuis","1")
  fibaro:debug("Druppel open+gesloten: G_IemandThuis set to 1")
  fibaro:call(75, "setProperty", "ui.Label1.value", "GeneralLock")
  fibaro:call(75, "setProperty", "ui.Label2.value", "Druppel open+gesloten: G_IemandThuis set to 1")
  fibaro:call(75, "setProperty", "ui.Label3.value", "INFORMATIONAL")
  fibaro:call(75, "pressButton", "3")   
  fibaro:sleep(100)
end

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