Fibaro

The Netatmo API is a set of webservices allowing developers and third parties to access Netatmo device's data.
Post Reply
Pernlubo
Posts: 2
Joined: 20 Mar 2020, 11:08

Fibaro

Post by Pernlubo » 20 Mar 2020, 11:10

Good morning, I have a netatmo meteo station and I would like to integrate it to Fibaro system. I have created the virtual points with scenes exactly based on descriptionhttps://forum.fibaro.com/files/file/93-netatmo-weather-station-vd-scene-standalone/. Based on this setup, the scene should get the information from meteo station via API. It seems that Fibaro is asking for data via API from meteo station but the meteo station is not sending them.
Could you please help me to solve this problem?

Pernlubo
Posts: 2
Joined: 20 Mar 2020, 11:08

Re: Fibaro

Post by Pernlubo » 20 Mar 2020, 11:27

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

--[[
NETATMO Weather Station scene - version 3.2 Standalone
Copyright (c) 2018-19 Zoran Sankovic - Sankotronic. All Rights Reserved.
--]]
-- CODE FOR USERS TO EDIT AND SETUP BEGINS HERE
-- SETUP NETATMO ACCOUNT
-- scene will not work without this settings so if you don't have client ID
-- and secret then first go to https://dev.netatmo.com add HC2 as app and get
-- your credentials.
local client_id = ""
local client_secret = ""
local username = ""
local password = ""

-- enter station MAC address in quotes. If you have more than one station then just
-- separate them by comma inside braces
local station_id = {"70:ee:50:3f:3d:c4"}

-- END OF CODE SECTION FOR USERS TO EDIT AND SETUP

-- THE CODE BELOW DOES NOT REQUIRE MODIFICATION BY THE USER
local hc=fibaro if hc:countScenes()>1 then os.exit() end
-- __fibaroSceneId is not documented feature, may stop working. If stop
-- working replace it with this scene ID number
local sceneId=__fibaroSceneId
local sId=tostring(sceneId)
local codeVersion,scVersion,chVersion="3.2","1.0","1.0"
local _name,_role="Netatmo weather scene","Netatmo scene"
local crt="Standalone ".._name.." version "..codeVersion.." - (c) 2018-19 Sankotronic"
-- other local settings
local token,request_body='',''
local currentTime=os.time()
local _refresh,sIDlen=4,17
local base_role="Netatmo base"
local scene_arg=hc:args()
-- Global variable names
local NetatmoWeatherName="NetatmoWeather"
local VirtualTableName="NetatmoMain"
local WeatherLangName="NetatmoLang"
-- debug variables
local bsdebug,addebug,evdebug=true,false,false
-- debug colors
local crc,okc,ekc,erc,evc,xec,cnc,xcc,tmc,stc="green","lightgreen","violet","red","orange","yellow","cyan","pink","magenta","lightgray"

function logbug(color,message)for line in message:gmatch("[^\010\013]+")do local txt=line:gsub("([\038\060\062])",function(c)return"&#"..string.byte(c)..";"end) hc:debug(('<span style="color:%s">%s</span>'):format(color,txt))end end

function parse(data)
local t=type(data)if t~="table" then return false,string.format("The data is not a table, it's a %s.",t)end
t=type(data.body)if t~="table" then return false,string.format("Table does not contain a table \"body\", it's a %s.",t)end
t=type(data.body.devices)if t~="table" then return false,string.format("Table does not contain a table \"body.devices\", it's a %s",t)end
return true,data.body.devices[1]
end

function checkSettings()
local function ab(t)logbug(erc,string.format("ERROR - %s.",t))return false end local a=true
if client_id=='' or client_secret=='' or username=='' or password=='' then
a=ab("You need to setup client_id, client_secret, username and password to use this scene")end
if #station_id==0 then a=ab("Netatmo weather station MAC address not defined. You need to add at least one station")
else for i=1,#station_id do if string.len(station_id)~=sIDlen then
a=ab(string.format("Netatmo weather station No.%s MAC address is invalid. Please check and correct",i))end end end
local wTglobal=hc:getGlobalValue(NetatmoWeatherName)
if wTglobal==nil then a=ab(string.format("Global Variable '%s' is missing.",NetatmoWeatherName))end
local ok,wT=pcall(json.decode,wTglobal)
if not ok then a=ab(string.format("Check Global Variable. JSON decode failed with error: %s",wT))end
if type(wT)~="table" then a=ab("Check contents of Global Variable. wT is not a table.")end
if wT.netatmo==nil then a=ab("wT table is missing a 'netatmo' field.")end
if a then
for k,v in pairs(station_id)do
if(k>#wT.netatmo)and(k-#wT.netatmo==1)then local old=#wT.netatmo local new=k
wT.netatmo[new]=wT.netatmo[old] wT.wsource[new]=wT.wsource[old] hc:setGlobal(NetatmoWeatherName,json.encode(wT))
logbug(okc,string.format("Added new set of values to global variable table for station: %s",v))
elseif(k>#wT.netatmo)and(k-#wT.netatmo>1)then
logbug(erc,"ERROR - Number of stations is not matching number of installed Weather status VDs")
a=ab("Either install VDs or add stations one by one and run scene after each added")
elseif(k<=#wT.netatmo)then
if deBug then logbug(okc,string.format("Global table data for station: %s read sucessfuly",v))end end
end end return a
end

function chkGlobal(n,d)
local function ab(t)if d then logbug(erc,string.format("ERROR - %s.",t))end return false end
local m,g,c,a=" data is corrupted","Global variable '","' is corrupted",true
local vT=hc:getGlobalValue(n) local ok, cT=pcall(json.decode, vT)
if vT==nil then a=ab(g..n.."' is missing.") else if not ok then a=ab("JSON decode failed with error: "..cT)else if type(cT)~="table" then a=ab(g..n.."' is not a table.")else
if n==WeatherLangName then if cT["en"]==nil then a=ab(g..n..c)end
elseif n==NetatmoWeatherName then if cT.version.code==nil then a=ab(g..n..c)else
if cT.netatmo==nil then a=ab(g..n.."' [netatmo]"..m)end end
end end end end return a end

function chkVDtable(role)
local room,ms="Unassigned","Netatmo Indoor Base station VD "
if hc:getGlobalValue(VirtualTableName)~=nil then local vT=json.decode(hc:getGlobalValue(VirtualTableName))
for k,v in pairs(vT)do if v.role==role then
if scene_arg~=nil and k==scene_arg[1] then if bsdebug then if v.roomID~=nil then room=hc:getRoomName(v.roomID)end
logbug(xcc,"Scene run by ["..k.."] "..v.us_name.." in room "..room)end end
if v.scene~=sceneId then if bsdebug then logbug(okc,string.format(ms.." No.%s found",v.stationNo))end
v.scene=sceneId hc:setGlobal(VirtualTableName,json.encode(vT))end end end
else logbug(erc,ms.."not found. Please install VD")end
end

function calcMinMax(min,max,val,dbg)
local ct=os.date("%H:%M",os.time()) if dbg==nil then dbg="" end
if((ct>="00:00")and(ct<="00:10"))then min=val max=val
if addebug then logbug(xec,"Resetting min/max values for "..dbg)end
else if val<min then min=val end if val>max then max=val end end
return min,max
end

function getDirection(sValue)
local lW=json.decode(hc:getGlobalValue(WeatherLangName))
local lng=lW.nlng
if((sValue>=0)and(sValue<=11))then return lW[lng].windDir.N elseif((sValue>11)and(sValue<=34))then return lW[lng].windDir.NNE
elseif((sValue>34)and(sValue<=56))then return lW[lng].windDir.NE elseif((sValue>56)and(sValue<=79))then return lW[lng].windDir.ENE
elseif((sValue>79)and(sValue<=101))then return lW[lng].windDir.E elseif((sValue>101)and(sValue<=124))then return lW[lng].windDir.ESE
elseif((sValue>124)and(sValue<=146))then return lW[lng].windDir.SE elseif((sValue>146)and(sValue<=169))then return lW[lng].windDir.SSE
elseif((sValue>169)and(sValue<=191))then return lW[lng].windDir.S elseif((sValue>191)and(sValue<=214))then return lW[lng].windDir.SSW
elseif((sValue>214)and(sValue<=236))then return lW[lng].windDir.SW elseif((sValue>236)and(sValue<=259))then return lW[lng].windDir.WSW
elseif((sValue>259)and(sValue<=281))then return lW[lng].windDir.W elseif((sValue>281)and(sValue<=304))then return lW[lng].windDir.WNW
elseif((sValue>304)and(sValue<=326))then return lW[lng].windDir.NW elseif((sValue>326)and(sValue<=349))then return lW[lng].windDir.NNW
elseif((sValue>349)and(sValue<=360))then return lW[lng].windDir.N else return "-" end
end

function oAuth(nextFunction)
if checkSettings()then
local request_body='grant_type=password&client_id='..client_id..'&client_secret='..client_secret..'&username='..username..'&password='..password.. '&scope=read_station'
getResponseData('https://api.netatmo.net/oauth2/token',request_body,
function(data)if(data.access_token~=nil)then token=data.access_token
logbug(okc,"netatmo-oAuth connected...")
getDevices()else logbug(erc,"ERROR - Netatmo-oAuth NOT connected. Will try again on next run...")end end)
end end

function getResponseData(url,body,func)
local http=net.HTTPClient()
http:request(url,{options={checkCertificate=false,method='POST',headers={['Content-Type']='application/x-www-form-urlencoded;charset=UTF-8'},data=body,timeout=40000},
success=function(response)
ok,msg=pcall(function()chk_data=json.decode(response.data)if type(chk_data)~="table" then error()end end)
if ok then if evdebug then logbug(okc,"Get response data decoded")end func(json.decode(response.data))else
if string.match(response.data,"<html>")=="<html>"then if string.match(response.data,"503")=="503"then
logbug(erc,"503 Service Temporarily Unavailable. Try again later. Netatmo team.")
elseif string.match(response.data,"405")=="405"then logbug(erc,"Not allowed. Change back to .net")
else logbug(erc,"HTML page returned instead of json data")
end end end end})
end

function getDevices()
for k,id in pairs(station_id)do
getResponseData('https://api.netatmo.net/api/getstations ... e_id="..id,
function(data)
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))local ok,msg=parse(data)
if ok then
if((currentTime-data.body.devices[1].last_status_store)<1800)then
logbug(cnc,string.format("Found Netatmo weather base station No. %s Name '%s'",k,data.body.devices[1].station_name))
wT.netatmo[k].fail=0
int_id=data.body.devices[1]._id
wT.netatmo[k]._id=data.body.devices[1]._id
wT.netatmo[k].name=data.body.devices[1].station_name
wT.netatmo[k].module_name=data.body.devices[1].module_name
wT.netatmo[k].wifi=data.body.devices[1].wifi_status
wT.netatmo[k].last_status_store=data.body.devices[1].last_status_store
wT.netatmo[k].firmware=data.body.devices[1].firmware
if data.body.user.administrative.unit==0 then
wT.netatmo[k].unit="metric" wT.netatmo[k].temp_unit=" \194\176C" wT.netatmo[k].rain_unit=" mm"
else wT.netatmo[k].unit="imperial" wT.netatmo[k].temp_unit=" \194\176F" wT.netatmo[k].rain_unit=" in" end
if data.body.user.administrative.windunit==0 then wT.netatmo[k].wind_unit=" km/h"
elseif data.body.user.administrative.windunit==1 then wT.netatmo[k].wind_unit=" mph"
elseif data.body.user.administrative.windunit==2 then wT.netatmo[k].wind_unit=" m/s"
elseif data.body.user.administrative.windunit==3 then wT.netatmo[k].wind_unit=" B"
else wT.netatmo[k].wind_unit=" kt." end
if data.body.user.administrative.pressureunit==0 then wT.netatmo[k].press_unit=" hPa"
elseif data.body.user.administrative.pressureunit==1 then wT.netatmo[k].press_unit=" inHg"
else wT.netatmo[k].press_unit=" mmHg" end
if data.body.user.administrative.feel_like_algo==0 then wT.netatmo[k].feels_like="Humidex"
else wT.netatmo[k].feels_like="Heat Index" end
wT.netatmo[k].country=data.body.user.administrative.country
wT.netatmo[k].reg_locale=data.body.user.administrative.reg_locale
wT.netatmo[k].lang=data.body.user.administrative.lang
wT.netatmo[k].place.altitude=data.body.devices[1].place.altitude
wT.netatmo[k].place.city=data.body.devices[1].place.city
wT.netatmo[k].place.country=data.body.devices[1].place.country
wT.netatmo[k].place.time_zone=data.body.devices[1].place.timezone
wT.netatmo[k].place.lon=data.body.devices[1].place.location[1]
wT.netatmo[k].place.lat=data.body.devices[1].place.location[2]
wT.netatmo[k].temp=data.body.devices[1].dashboard_data.Temperature
wT.netatmo[k].temp_min=data.body.devices[1].dashboard_data.min_temp
wT.netatmo[k].temp_max=data.body.devices[1].dashboard_data.max_temp
if wT.netatmo[k].unit=="imperial" then wT.netatmo[k].temp=((wT.netatmo[k].temp*9/5)+32)
wT.netatmo[k].temp_min=((wT.netatmo[k].temp_min*9/5)+32) wT.netatmo[k].temp_max=((wT.netatmo[k].temp_max*9/5)+32) end
wT.netatmo[k].temp_trend=data.body.devices[1].dashboard_data.temp_trend
wT.netatmo[k].humid=data.body.devices[1].dashboard_data.Humidity
wT.netatmo[k].humid_min, wT.netatmo[k].humid_max=calcMinMax(wT.netatmo[k].humid_min, wT.netatmo[k].humid_max, wT.netatmo[k].humid,"indoor base humidity")
wT.netatmo[k].abs_press=data.body.devices[1].dashboard_data.AbsolutePressure
wT.netatmo[k].press=tonumber(string.format('%.0f',data.body.devices[1].dashboard_data.Pressure))
wT.netatmo[k].press_min, wT.netatmo[k].press_max=calcMinMax(wT.netatmo[k].press_min, wT.netatmo[k].press_max, wT.netatmo[k].press,"air pressure")
wT.netatmo[k].press_trend=data.body.devices[1].dashboard_data.pressure_trend
wT.netatmo[k].noise=data.body.devices[1].dashboard_data.Noise
wT.netatmo[k].co2=data.body.devices[1].dashboard_data.CO2
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
if evdebug then logbug(xec,"Searching for Wind, Rain, Outdoor and Indoor modules data...")end
local indoorNo=0
for _,v in pairs(data.body.devices[1].modules)do
if(v.type=='NAModule1')then
outdoor_id=v._id
if outdoor_id~=nil and((currentTime-v.last_message)<1800)then
if bsdebug then logbug(okc,string.format("%s module found. Battery level: %s",v.module_name,v.battery_percent)) end
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].outm.fail=0
wT.netatmo[k].outm.name=v.module_name
wT.netatmo[k].outm._id=v._id
wT.netatmo[k].outm.batt=v.battery_percent
wT.netatmo[k].outm._rf=(100-v.rf_status)
wT.netatmo[k].outm.last_message=v.last_message
wT.netatmo[k].outm.last_seen=v.last_seen
wT.netatmo[k].outm.firmware=v.firmware
wT.netatmo[k].outm.temp_min=v.dashboard_data.min_temp
wT.netatmo[k].outm.temp_max=v.dashboard_data.max_temp
if wT.netatmo[k].unit=="imperial" then
wT.netatmo[k].outm.temp_min=((wT.netatmo[k].outm.temp_min*9/5)+32)
wT.netatmo[k].outm.temp_max=((wT.netatmo[k].outm.temp_max*9/5)+32)end
wT.netatmo[k].outm.temp_trend=v.dashboard_data.temp_trend
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
getmeasureOutdoor(k)
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].outm.fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))
logbug(erc,"ERROR - Outdoor module data not available")end
elseif(v.type=='NAModule2')then
wind_id=v._id
if wind_id~=nil and((currentTime-v.last_message)<1800)then
if bsdebug then logbug(okc,string.format("%s module found. Battery level: %s",v.module_name,v.battery_percent))end
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].wind.fail=0
wT.netatmo[k].wind.name=v.module_name
wT.netatmo[k].wind._id=v._id
wT.netatmo[k].wind.batt=v.battery_percent
wT.netatmo[k].wind._rf=(100-v.rf_status)
wT.netatmo[k].wind.last_message=v.last_message
wT.netatmo[k].wind.last_seen=v.last_seen
wT.netatmo[k].wind.firmware=v.firmware
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
getmeasureWind(k)
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].wind.fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))
logbug(erc,"ERROR - Wind module data not available")end
elseif(v.type=='NAModule3')then
rain_id=v._id
if rain_id~=nil and((currentTime-v.last_message)<1800)then
if bsdebug then logbug(okc,string.format("%s module found. Battery level: %s",v.module_name,v.battery_percent))end
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].rain.fail=0
wT.netatmo[k].rain.name=v.module_name
wT.netatmo[k].rain._id=v._id
wT.netatmo[k].rain.batt=v.battery_percent
wT.netatmo[k].rain._rf=(100-v.rf_status)
wT.netatmo[k].rain.last_message=v.last_message
wT.netatmo[k].rain.last_seen=v.last_seen
wT.netatmo[k].rain.firmware=v.firmware
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
readRain(k,wT.netatmo[k].rain.name)
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[k].rain.fail=1
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
logbug(erc,"ERROR - Rain module data not available")end
elseif(v.type=="NAModule4")then
indoorNo=indoorNo+1
indoor_id=v._id
if indoor_id~=nil and((currentTime-v.last_message)<1800)then
if bsdebug then logbug(okc,string.format( "%s additional indoor module found. Battery level: %s",v.module_name,v.battery_percent)) end
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
if wT.netatmo[k].intm[indoorNo]~=nil then
wT.netatmo[k].intm[indoorNo].fail=0
wT.netatmo[k].intm[indoorNo].name=v.module_name
wT.netatmo[k].intm[indoorNo]._id=v._id
wT.netatmo[k].intm[indoorNo].batt=v.battery_percent
wT.netatmo[k].intm[indoorNo]._rf=(100-v.rf_status)
wT.netatmo[k].intm[indoorNo].last_message=v.last_message
wT.netatmo[k].intm[indoorNo].last_seen=v.last_seen
wT.netatmo[k].intm[indoorNo].firmware=v.firmware
wT.netatmo[k].intm[indoorNo].temp_min=v.dashboard_data.min_temp
wT.netatmo[k].intm[indoorNo].temp_max=v.dashboard_data.max_temp
if wT.netatmo[k].unit=="imperial" then
wT.netatmo[k].intm[indoorNo].temp_min=((wT.netatmo[k].intm[indoorNo].temp_min*9/5)+32)
wT.netatmo[k].intm[indoorNo].temp_max=((wT.netatmo[k].intm[indoorNo].temp_max*9/5)+32)end
if evdebug then logbug(xec,"Updated existing data in table")end
else tmp_min=v.dashboard_data.min_temp tmp_max=v.dashboard_data.max_temp
if wT.netatmo[k].unit=="imperial" then tmp_min=((tmp_min*9/5)+32) tmp_max=((tmp_max*9/5)+32)end
wT.netatmo[k].intm[indoorNo]={name=v.module_name,_id=v._id,batt=v.battery_percent,_rf=(100-v.rf_status),fail=0,failch=0,
temp=tmp_max,temp_min=tmp_min,temp_max=tmp_max,temp_trend="",humid=40,humid_min=99,humid_max=0}
if evdebug then logbug(xec,"Added new data in table")end end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))getmeasureIndoor(k,indoorNo)
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
if wT.netatmo[k].intm[indoorNo]~=nil then wT.netatmo[k].intm[indoorNo].fail=1
else wT.netatmo[k].intm[indoorNo]={name="Indoor"..indoorNo,_id="",batt=0,_rf=0,fail=1,failch=0,temp=0,temp_min=40,temp_max=0,
temp_trend="",humid=40,humid_min=99,humid_max=0} end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
logbug(erc,string.format("ERROR - Additional indoor module No. '%s' data not available!",indoorNo))
end end end
else logbug(erc,string.format("Netatmo base station ID: '%s' could not be found!",id))
wT.netatmo[k].fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
else logbug(erc,string.format("Netatmo base station ID: '%s' could not be retreived!",id))
logbug(erc,string.format("ERROR returned: %s\nWill try again on next run...",msg))
wT.netatmo[k].fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
end) end end

function getmeasureIndoor(n,intmNo)
local request_body_indoor='access_token='..token..'&device_id='..int_id..'&module_id='..indoor_id..'&scale=max&type=humidity,temperature,CO2&date_end=last'
getResponseData('https://api.netatmo.net/api/getmeasure', request_body_indoor,
function(getData)
if getData.body~=nil then
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
wT.netatmo[n].intm[intmNo].fail=0
if evdebug then logbug(cnc,string.format("Start reading %s",wT.netatmo[n].intm[intmNo].name))end
wT.netatmo[n].intm[intmNo].humid=getData.body[1].value[1][1]
wT.netatmo[n].intm[intmNo].humid_min,wT.netatmo[n].intm[intmNo].humid_max=calcMinMax(wT.netatmo[n].intm[intmNo].humid_min,wT.netatmo[n].intm[intmNo].humid_max,wT.netatmo[n].intm[intmNo].humid,"indoor No."..intmNo.." humidity")
wT.netatmo[n].intm[intmNo].temp=getData.body[1].value[1][2]
if wT.netatmo[n].unit=="imperial" then wT.netatmo[n].intm[intmNo].temp=((wT.netatmo[n].intm[intmNo].temp*9/5)+32)end
wT.netatmo[n].intm[intmNo].co2=getData.body[1].value[1][3]
if addebug then logbug(evc,string.format("%s temperature: %s%s",wT.netatmo[n].intm[intmNo].name,wT.netatmo[n].intm[intmNo].temp,wT.netatmo[n].temp_unit))end
if addebug then logbug(evc,string.format("%s humidity: %s %%",wT.netatmo[n].intm[intmNo].name,wT.netatmo[n].intm[intmNo].humid))end
if evdebug then logbug(xec,string.format("End reading %s",wT.netatmo[n].intm[intmNo].name))end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
logbug(erc,string.format("ERROR - Could not get %s module data. Will try again next run...",wT.netatmo[n].intm[intmNo].name))
wT.netatmo[n].intm[intmNo].fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
end) end

function getmeasureOutdoor(n)
local request_body_outdoor='access_token='..token..'&device_id='..int_id..'&module_id='..outdoor_id..'&scale=max&type=humidity,temperature&date_end=last'
getResponseData('https://api.netatmo.net/api/getmeasure' ... dy_outdoor,
function(getData)
if getData.body~=nil then
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))wT.netatmo[n].outm.fail=0
if evdebug then logbug(cnc,string.format("Start reading %s",wT.netatmo[n].outm.name))end
wT.netatmo[n].outm.humid=getData.body[1].value[1][1]
wT.netatmo[n].outm.humid_min,wT.netatmo[n].outm.humid_max=calcMinMax(wT.netatmo[n].outm.humid_min,wT.netatmo[n].outm.humid_max,wT.netatmo[n].outm.humid,"outdoor humidity")
wT.netatmo[n].outm.temp=getData.body[1].value[1][2]
if wT.netatmo[n].unit=="imperial" then wT.netatmo[n].outm.temp=((wT.netatmo[n].outm.temp*9/5)+32)end
if addebug then logbug(evc,string.format("Outside temperature: %s%s",wT.netatmo[n].outm.temp,wT.netatmo[n].temp_unit))end
if addebug then logbug(evc,string.format("Outside humidity: %s %%",wT.netatmo[n].outm.humid))end
if evdebug then logbug(xec,string.format("End reading %s",wT.netatmo[n].outm.name))end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
logbug(erc,string.format("ERROR - Could not get %s module data. Will try again next run...",wT.netatmo[n].outm.name))
wT.netatmo[n].outm.fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
end) end

function getmeasureWind(n)
local request_body_wind='access_token='..token..'&device_id='..int_id..'&module_id='..wind_id..'&scale=max&type=WindStrength,WindAngle,GustStrength,GustAngle&date_end=last'
getResponseData('https://api.netatmo.net/api/getmeasure' ... _body_wind,
function(getData)
if getData.body~=nil then
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))wT.netatmo[n].wind.fail=0
if evdebug then logbug(cnc,string.format("Start reading %s",wT.netatmo[n].wind.name))end
wT.netatmo[n].wind.speed=getData.body[1].value[1][1]
min, wT.netatmo[n].wind.speed_max=calcMinMax(0,wT.netatmo[n].wind.speed_max,wT.netatmo[n].wind.speed,"wind speed")
if wT.netatmo[n].wind_unit==" mph" then
wT.netatmo[n].wind.speed=tonumber(string.format('%.0f',(wT.netatmo[n].wind.speed*0.621371)))
wT.netatmo[n].wind.speed_max=tonumber(string.format('%.0f',(wT.netatmo[n].wind.speed_max*0.621371)))
elseif wT.netatmo[n].wind_unit==" m/s" then
wT.netatmo[n].wind.speed=tonumber(string.format('%.1f',(wT.netatmo[n].wind.speed*0.277778)))
wT.netatmo[n].wind.speed_max=tonumber(string.format('%.1f',(wT.netatmo[n].wind.speed_max*0.277778)))
elseif wT.netatmo[n].wind_unit==" B" then
if wT.netatmo[n].wind.speed<6 then wT.netatmo[n].wind.speed=1
elseif wT.netatmo[n].wind.speed<12 then wT.netatmo[n].wind.speed=2
elseif wT.netatmo[n].wind.speed<20 then wT.netatmo[n].wind.speed=3
elseif wT.netatmo[n].wind.speed<29 then wT.netatmo[n].wind.speed=4
elseif wT.netatmo[n].wind.speed<39 then wT.netatmo[n].wind.speed=5
elseif wT.netatmo[n].wind.speed<51 then wT.netatmo[n].wind.speed=6
elseif wT.netatmo[n].wind.speed<62 then wT.netatmo[n].wind.speed=7
elseif wT.netatmo[n].wind.speed<75 then wT.netatmo[n].wind.speed=8
elseif wT.netatmo[n].wind.speed<89 then wT.netatmo[n].wind.speed=9
elseif wT.netatmo[n].wind.speed<103 then wT.netatmo[n].wind.speed=10
elseif wT.netatmo[n].wind.speed<118 then wT.netatmo[n].wind.speed=11
else wT.netatmo[n].wind.speed=12 end
if wT.netatmo[n].wind.speed_max<6 then wT.netatmo[n].wind.speed_max=1
elseif wT.netatmo[n].wind.speed_max<12 then wT.netatmo[n].wind.speed_max=2
elseif wT.netatmo[n].wind.speed_max<20 then wT.netatmo[n].wind.speed_max=3
elseif wT.netatmo[n].wind.speed_max<29 then wT.netatmo[n].wind.speed_max=4
elseif wT.netatmo[n].wind.speed_max<39 then wT.netatmo[n].wind.speed_max=5
elseif wT.netatmo[n].wind.speed_max<51 then wT.netatmo[n].wind.speed_max=6
elseif wT.netatmo[n].wind.speed_max<62 then wT.netatmo[n].wind.speed_max=7
elseif wT.netatmo[n].wind.speed_max<75 then wT.netatmo[n].wind.speed_max=8
elseif wT.netatmo[n].wind.speed_max<89 then wT.netatmo[n].wind.speed_max=9
elseif wT.netatmo[n].wind.speed_max<103 then wT.netatmo[n].wind.speed_max=10
elseif wT.netatmo[n].wind.speed_max<118 then wT.netatmo[n].wind.speed_max=11
else wT.netatmo[n].wind.speed_max=12 end
elseif wT.netatmo[n].wind_unit==" kt." then
wT.netatmo[n].wind.speed=tonumber(string.format('%.0f',(wT.netatmo[n].wind.speed*0.539956803)))
wT.netatmo[n].wind.speed_max=tonumber(string.format('%.0f',(wT.netatmo[n].wind.speed_max*0.539956803)))end
wT.netatmo[n].wind.deg=getData.body[1].value[1][2]
wT.netatmo[n].wind.dir=getDirection(wT.netatmo[n].wind.deg)
-- get gusts
wT.netatmo[n].wind.gust=getData.body[1].value[1][3]
min, wT.netatmo[n].wind.gust_max=calcMinMax(0,wT.netatmo[n].wind.gust_max,wT.netatmo[n].wind.gust,"gust speed")
if wT.netatmo[n].wind_unit==" mph" then
wT.netatmo[n].wind.gust=tonumber(string.format('%.0f',(wT.netatmo[n].wind.gust*0.621371)))
wT.netatmo[n].wind.gust_max=tonumber(string.format('%.0f',(wT.netatmo[n].wind.gust_max*0.621371)))
elseif wT.netatmo[n].wind_unit==" m/s" then
wT.netatmo[n].wind.gust=tonumber(string.format('%.1f',(wT.netatmo[n].wind.gust*0.277778)))
wT.netatmo[n].wind.gust_max=tonumber(string.format('%.1f',(wT.netatmo[n].wind.gust_max*0.277778)))
elseif wT.netatmo[n].wind_unit==" B" then
if wT.netatmo[n].wind.gust<6 then wT.netatmo[n].wind.gust=1
elseif wT.netatmo[n].wind.gust<12 then wT.netatmo[n].wind.gust=2
elseif wT.netatmo[n].wind.gust<20 then wT.netatmo[n].wind.gust=3
elseif wT.netatmo[n].wind.gust<29 then wT.netatmo[n].wind.gust=4
elseif wT.netatmo[n].wind.gust<39 then wT.netatmo[n].wind.gust=5
elseif wT.netatmo[n].wind.gust<51 then wT.netatmo[n].wind.gust=6
elseif wT.netatmo[n].wind.gust<62 then wT.netatmo[n].wind.gust=7
elseif wT.netatmo[n].wind.gust<75 then wT.netatmo[n].wind.gust=8
elseif wT.netatmo[n].wind.gust<89 then wT.netatmo[n].wind.gust=9
elseif wT.netatmo[n].wind.gust<103 then wT.netatmo[n].wind.gust=10
elseif wT.netatmo[n].wind.gust<118 then wT.netatmo[n].wind.gust=11
else wT.netatmo[n].wind.gust=12 end
if wT.netatmo[n].wind.gust_max<6 then wT.netatmo[n].wind.gust_max=1
elseif wT.netatmo[n].wind.gust_max<12 then wT.netatmo[n].wind.gust_max=2
elseif wT.netatmo[n].wind.gust_max<20 then wT.netatmo[n].wind.gust_max=3
elseif wT.netatmo[n].wind.gust_max<29 then wT.netatmo[n].wind.gust_max=4
elseif wT.netatmo[n].wind.gust_max<39 then wT.netatmo[n].wind.gust_max=5
elseif wT.netatmo[n].wind.gust_max<51 then wT.netatmo[n].wind.gust_max=6
elseif wT.netatmo[n].wind.gust_max<62 then wT.netatmo[n].wind.gust_max=7
elseif wT.netatmo[n].wind.gust_max<75 then wT.netatmo[n].wind.gust_max=8
elseif wT.netatmo[n].wind.gust_max<89 then wT.netatmo[n].wind.gust_max=9
elseif wT.netatmo[n].wind.gust_max<103 then wT.netatmo[n].wind.gust_max=10
elseif wT.netatmo[n].wind.gust_max<118 then wT.netatmo[n].wind.gust_max=11
else wT.netatmo[n].wind.gust_max=12 end
elseif wT.netatmo[n].wind_unit==" kt." then
wT.netatmo[n].wind.gust=tonumber(string.format('%.0f',(wT.netatmo[n].wind.gust*0.539956803)))
wT.netatmo[n].wind.gust_max=tonumber(string.format('%.0f',(wT.netatmo[n].wind.gust_max*0.539956803)))end
wT.netatmo[n].wind.gust_deg=getData.body[1].value[1][4]
wT.netatmo[n].wind.gust_dir=getDirection(wT.netatmo[n].wind.gust_deg)
if addebug then logbug(evc,string.format("Wind speed: %s%s - angle: %s",wT.netatmo[n].wind.speed,wT.netatmo[n].wind_unit,wT.netatmo[n].wind.deg))end
if addebug then logbug(evc,string.format("Gust speed: %s%s - angle: %s",wT.netatmo[n].wind.gust,wT.netatmo[n].wind_unit,wT.netatmo[n].wind.gust_deg))end
if evdebug then logbug(xec,string.format("End reading %s",wT.netatmo[n].wind.name))end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
logbug(erc,string.format("ERROR - Could not get %s module data. Will try again next run...",wT.netatmo[n].wind.name))
wT.netatmo[n].wind.fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
end) end

function readRain(k,name)
if evdebug then logbug(cnc,string.format("Start reading %s",name))end
getSumRain(60*60,'hour',k)getSumRain(60*60*24,'day',k)getSumRain(60*60*24*7,'week',k,name)getSumRain(60*60*24*30,'month',k,name)
end

function getSumRain(duration,variable,m)
local now=os.time()
local request_body_rain='access_token='..token..'&device_id='..int_id..'&module_id='..rain_id..'&scale=1hour&type=sum_rain&real_time=true&date_begin='..now-duration
getResponseData('https://api.netatmo.net/api/getmeasure' ... _body_rain,
function(data)
if data.body~=nil then
local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))wT.netatmo[m].rain.fail=0 local sum_rain=0
for k,v in pairs(data.body)do for l,w in pairs(v.value)do sum_rain=sum_rain+w[1] end end
if wT.netatmo[m].unit=="imperial" then sum_rain=(sum_rain*0.039370)end
if variable=="hour" then wT.netatmo[m].rain.hour=sum_rain
elseif variable=="day" then wT.netatmo[m].rain.day=sum_rain
elseif variable=="week" then wT.netatmo[m].rain.week=sum_rain
else wT.netatmo[m].rain.month=sum_rain end
if addebug then logbug(evc,string.format("Rainfall: %s %s (%s)",sum_rain,wT.netatmo[m].rain_unit,variable))end
hc:setGlobal(NetatmoWeatherName,json.encode(wT))
else local wT=json.decode(hc:getGlobalValue(NetatmoWeatherName))
logbug(erc,string.format("ERROR - Could not get %s module data. Will try again next run...",wT.netatmo[m].rain.name))
wT.netatmo[m].rain.fail=1 hc:setGlobal(NetatmoWeatherName,json.encode(wT))end
end) end

-- main part
logbug(crc,crt)chkVDtable(base_role)oAuth()
Last edited by Daegil_Netatmo on 28 May 2020, 14:16, edited 1 time in total.
Reason: Deletion of personnal information.

Post Reply

Return to “Netatmo API”