Urban Weather Station Netatmo LUA Script for Vera

Here is a LUA script to collect data from the REST API Netatmo to my Vera. At the moment a single script pushes all the data in a Vcontainer.

http://forum.netatmo.com/viewtopic.php?f=5&t=1026&sid=ddb92e4b8e5fbd371c15d0e30deec1ee
http://www.touteladomotique.com/forum/viewtopic.php?f=48&t=9905&p=80350#p80350

------------------------------------------------------------------------
-- NAME: netatmo-vera.lua
-- AUTHOR: S?bastien Joly
-- DATE  : 29/01/2013
-- COMMENT: Collecter les donn?es d'une station Netatmo
------------------------------------------------------------------------
-- MODIFIER LES ELEMENTS D'AUTHENTIFICATION PAR VOS DONNEES
------------------------------------------------------------------------
local s_client_id = "XXXXXX"
local s_client_secret = "XXXXXX"
local s_username = "XXXXXX"
local s_password = "XXXXXX"
------------------------------------------------------------------------
local request_body = "grant_type=password&client_id=" .. s_client_id .."&client_secret=" .. s_client_secret .. "&username=" .. s_username .. "&password=" .. s_password
------------------------------------------------------------------------
-- LIBRAIRIES
------------------------------------------------------------------------
require 'ltn12'
require 'socket.http'
json = require("json")-- PAS NATIF SUR LA VERA
------------------------------------------------------------------------
-- FONCTION HTTP POST
------------------------------------------------------------------------
function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
  url = p_url;
  method = "POST";
  headers =
  {
    ["Content-Type"] = "application/x-www-form-urlencoded";
    ["Content-Length"] = #p_body;
  };
  source = ltn12.source.string(p_body);
  sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end
------------------------------------------------------------------------
-- PROCEDURE
------------------------------------------------------------------------
reponsepost = posthttp("https://api.netatmo.net/oauth2/token",request_body)
access_token = reponsepost.access_token
reponsepost = posthttp("https://api.netatmo.net/api/devicelist","access_token=" .. access_token)
module_interne = reponsepost.body.devices[1]._id
module_externe = reponsepost.body.modules[1]._id
reponsepost = posthttp("https://api.netatmo.net/api/getmeasure","access_token=" ..access_token .."&device_id=" .. module_interne .. "&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last")
luup.log ("---------------")
temperature_interieure =reponsepost.body[1].value[1][1]
co2 =reponsepost.body[1].value[1][2]
humidite_interne =reponsepost.body[1].value[1][3]
pression =reponsepost.body[1].value[1][4]
bruit =reponsepost.body[1].value[1][5]
luup.log(temperature_interieure)
luup.log (co2)
luup.log (humidite_interne)
luup.log (pression)
luup.log (bruit)
reponsepost = posthttp("https://api.netatmo.net/api/getmeasure","access_token=" ..access_token .."&device_id=" .. module_interne .. "&module_id=" .. module_externe .. "&scale=max&type=Temperature,Humidity&date_end=last")
temperature_externe =reponsepost.body[1].value[1][1]
humidite_externe =reponsepost.body[1].value[1][2]
luup.log(temperature_externe)
luup.log (humidite_externe)
luup.log ("---------------")
------------------------------------------------------------------------
-- CHARGEMENT DES VARIABLES LOCALES DANS LES DEUX VCONTAINER
------------------------------------------------------------------------
local SID_Vc = "urn:upnp-org:serviceId:VContainer1"
local ID_modint = 34 -- pour ma vera Module int?rieur VC ID #34
local ID_modext = 35 -- pour ma vera Module ext?rieur VC ID #35
if (status == 0) then
local currentTime = os.date("*t")
currentTime = currentTime.hour .. ":" .. currentTime.min
      luup.variable_set(SID_Vc, "VariableName3","Heure", ID_modext)
         luup.variable_set(SID_Vc, "Variable3", currentTime, ID_modext)
-- temperature exterieure
      luup.variable_set(SID_Vc, "VariableName1","Temp?rature", ID_modext)
         luup.variable_set(SID_Vc, "Variable1", temperature_externe, ID_modext)
-- humidite exterieure
      luup.variable_set(SID_Vc, "VariableName2","Humidit?", ID_modext)
         luup.variable_set(SID_Vc, "Variable2", humidite_externe, ID_modext)
-- temperature interieure
        luup.variable_set(SID_Vc, "VariableName1","Temp?rature ?C", ID_modint)
           luup.variable_set(SID_Vc, "Variable1", temperature_interieure, ID_modint)
-- Humidite interieure
      luup.variable_set(SID_Vc, "VariableName2","Humidit? %", ID_modint)
         luup.variable_set(SID_Vc, "Variable2", humidite_interne, ID_modint) 
-- Pression
      luup.variable_set(SID_Vc, "VariableName3","Pression Hpa", ID_modint)
         luup.variable_set(SID_Vc, "Variable3", pression , ID_modint) 
-- CO?
      luup.variable_set(SID_Vc, "VariableName4","CO2 PPM", ID_modint)
         luup.variable_set(SID_Vc, "Variable4", co2, ID_modint) 
-- Bruit
      luup.variable_set(SID_Vc, "VariableName5","Bruit db", ID_modint)
         luup.variable_set(SID_Vc, "Variable5", bruit, ID_modint) 
end
------------------------------------------------------------------------
-- FIN
------------------------------------------------------------------------

[quote=“captainigloo, post:1, topic:174148”]Here is a LUA script to collect data from the REST API Netatmo to my Vera. At the moment a single script pushes all the data in a Vcontainer.

http://forum.netatmo.com/viewtopic.php?f=5&t=1026&sid=ddb92e4b8e5fbd371c15d0e30deec1ee
http://www.touteladomotique.com/forum/viewtopic.php?f=48&t=9905&p=80350#p80350

[code]

– NAME: netatmo-vera.lua
– AUTHOR: S?bastien Joly
– DATE : 29/01/2013
– COMMENT: Collecter les donn?es d’une station Netatmo

– MODIFIER LES ELEMENTS D’AUTHENTIFICATION PAR VOS DONNEES

local s_client_id = “XXXXXX”
local s_client_secret = “XXXXXX”
local s_username = “XXXXXX”
local s_password = “XXXXXX”

local request_body = “grant_type=password&client_id=” … s_client_id …"&client_secret=" … s_client_secret … “&username=” … s_username … “&password=” … s_password

– LIBRAIRIES

require ‘ltn12’
require ‘socket.http’
json = require(“json”)-- PAS NATIF SUR LA VERA

– FONCTION HTTP POST

function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
url = p_url;
method = “POST”;
headers =
{
[“Content-Type”] = “application/x-www-form-urlencoded”;
[“Content-Length”] = #p_body;
};
source = ltn12.source.string(p_body);
sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end

– PROCEDURE

reponsepost = posthttp(“https://api.netatmo.net/oauth2/token”,request_body)
access_token = reponsepost.access_token
reponsepost = posthttp(“https://api.netatmo.net/api/devicelist","access_token=” … access_token)
module_interne = reponsepost.body.devices[1]._id
module_externe = reponsepost.body.modules[1]._id
reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … module_interne … “&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last”)
luup.log ("---------------")
temperature_interieure =reponsepost.body[1].value[1][1]
co2 =reponsepost.body[1].value[1][2]
humidite_interne =reponsepost.body[1].value[1][3]
pression =reponsepost.body[1].value[1][4]
bruit =reponsepost.body[1].value[1][5]
luup.log(temperature_interieure)
luup.log (co2)
luup.log (humidite_interne)
luup.log (pression)
luup.log (bruit)
reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … module_interne … “&module_id=” … module_externe … “&scale=max&type=Temperature,Humidity&date_end=last”)
temperature_externe =reponsepost.body[1].value[1][1]
humidite_externe =reponsepost.body[1].value[1][2]
luup.log(temperature_externe)
luup.log (humidite_externe)
luup.log ("---------------")

– CHARGEMENT DES VARIABLES LOCALES DANS LES DEUX VCONTAINER

local SID_Vc = “urn:upnp-org:serviceId:VContainer1”
local ID_modint = 34 – pour ma vera Module int?rieur VC ID #34
local ID_modext = 35 – pour ma vera Module ext?rieur VC ID #35
if (status == 0) then
local currentTime = os.date("*t")
currentTime = currentTime.hour … “:” … currentTime.min
luup.variable_set(SID_Vc, “VariableName3”,“Heure”, ID_modext)
luup.variable_set(SID_Vc, “Variable3”, currentTime, ID_modext)
– temperature exterieure
luup.variable_set(SID_Vc, “VariableName1”,“Temp?rature”, ID_modext)
luup.variable_set(SID_Vc, “Variable1”, temperature_externe, ID_modext)
– humidite exterieure
luup.variable_set(SID_Vc, “VariableName2”,“Humidit?”, ID_modext)
luup.variable_set(SID_Vc, “Variable2”, humidite_externe, ID_modext)
– temperature interieure
luup.variable_set(SID_Vc, “VariableName1”,“Temp?rature ?C”, ID_modint)
luup.variable_set(SID_Vc, “Variable1”, temperature_interieure, ID_modint)
– Humidite interieure
luup.variable_set(SID_Vc, “VariableName2”,“Humidit? %”, ID_modint)
luup.variable_set(SID_Vc, “Variable2”, humidite_interne, ID_modint)
– Pression
luup.variable_set(SID_Vc, “VariableName3”,“Pression Hpa”, ID_modint)
luup.variable_set(SID_Vc, “Variable3”, pression , ID_modint)
– CO?
luup.variable_set(SID_Vc, “VariableName4”,“CO2 PPM”, ID_modint)
luup.variable_set(SID_Vc, “Variable4”, co2, ID_modint)
– Bruit
luup.variable_set(SID_Vc, “VariableName5”,“Bruit db”, ID_modint)
luup.variable_set(SID_Vc, “Variable5”, bruit, ID_modint)
end

– FIN

[/code][/quote]

I was thinking about purchasing the Netatmo. Could you tell me what you are doing with the script above. thanks,

For the English speakers:

As far as I can figure it and keeping in mind I don’t have a Netatmo:

  1. the code requires a JSON library: “PAS NATIF SUR LA VERA”. If you install the “Google Calendar” plugin, a JSON library will be installed on your Vera as a byproduct of the install process. That solves this problem.

  2. the program uses two “VContainers”. Look in the app store/market place and install the “VContainer” plugin and then Create a second one. Take note of their device numbers and stick the numbers in the Netatmo code. One is for the “Internal” variables ie inside the house (ID_modint) and one for the “External” variables ie outside the house (ID_modext).

  3. looks like the code is meant to go in a Scene. The scene should probably be triggered by a schedule, say every ten minutes - I think the Netatmo updates every 5 minutes?

  4. the data can be plotted in dataMine by plotting the VContainer variables.

  5. you need to make sure the authentication is set up to suit your device:

[code]------------------------------------------------------------------------
– MODIFIER LES ELEMENTS D’AUTHENTIFICATION PAR VOS DONNEES

local s_client_id = “XXXXXX”
local s_client_secret = “XXXXXX”
local s_username = “XXXXXX”
local s_password = “XXXXXX”[/code]

  1. the code has suffered from internalization or is that internalisation. Some of the variables have question marks in them and these need to be hunted down and corrected. Two examples:
    *Temp?rature
    *Humidit?

Translating the French to English is simple with the aid of Google Translate. Hoping someone will do the work and post the translated code. Could this be made into a plugin - yes. Is that necessary? Maybe.

English version - hopefully it still works !!

[code]------------------------------------------------------------------------
– NAME: netatmo-vera.lua
– AUTHOR: Sebastien Joly
– DATE: 29/01/2013
– COMMENT: Get the data from a Netatmo station
– Requires the use of two Vera VContainer plugins and a JSON library


– Change these values to match the authentication used for your Netatmo account
– You will also need to put in the VContainer IDs further below

local s_client_id = “XXXXXX”
local s_client_secret = “XXXXXX”
local s_username = “XXXXXX”
local s_password = “XXXXXX”


local request_body = “grant_type=password&client_id=” … s_client_id …"&client_secret=" … s_client_secret … “&username=” … s_username … “&password=” … s_password


– Libraries

require ‘ltn12’
require ‘socket.http’

– JSON is not native to Vera. You will need to install a plugin
– that also installs a json library as a side effect / byproduct
– Suggest the Google Calendar plugin be used to do this
json = require(“json”)


– HTTP POST function

function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
url = p_url;
method = “POST”;
headers =
{
[“Content-Type”] = “application/x-www-form-urlencoded”;
[“Content-Length”] = #p_body;
};
source = ltn12.source.string(p_body);
sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end


– Main procedure

reponsepost = posthttp(“https://api.netatmo.net/oauth2/token”,request_body)
access_token = reponsepost.access_token
reponsepost = posthttp(“https://api.netatmo.net/api/devicelist","access_token=” … access_token)

moduleInside = reponsepost.body.devices[1]._id
moduleOutside = reponsepost.body.modules[1]._id

reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … moduleInside … “&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last”)
luup.log ("---------------")

temperatureInside = reponsepost.body[1].value[1][1]
co2 = reponsepost.body[1].value[1][2]
humidityInside = reponsepost.body[1].value[1][3]
pressure = reponsepost.body[1].value[1][4]
noiseLevel = reponsepost.body[1].value[1][5]

luup.log (temperatureInside)
luup.log (co2)
luup.log (humidityInside)
luup.log (pressure)
luup.log (noiseLevel)

reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … moduleInside … “&module_id=” … moduleOutside … “&scale=max&type=Temperature,Humidity&date_end=last”)
temperatureOutside = reponsepost.body[1].value[1][1]
humidityOutside = reponsepost.body[1].value[1][2]

luup.log (temperatureOutside)
luup.log (humidityOutside)
luup.log ("---------------")


– Put the local variables into two VCONTAINER plugins
– Change the device two IDs to match yours

local INSIDE_MODULE_ID = 34 – VContainer ID: inside
local OUTSIDE_MODULE_ID = 35 – VContainer ID: outside

local VC_SID = “urn:upnp-org:serviceId:VContainer1”

if (status == 0) then
local currentTime = os.date("*t")
currentTime = currentTime.hour … “:” … currentTime.min
luup.variable_set(VC_SID, “VariableName3”,“Hour”, OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, “Variable3”, currentTime, OUTSIDE_MODULE_ID)

-- temperature outside
luup.variable_set(VC_SID, "VariableName1","Temperature", OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable1", temperatureOutside, OUTSIDE_MODULE_ID)

-- humidity outside
luup.variable_set(VC_SID, "VariableName2","Humidity", OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable2", humidityOutside, OUTSIDE_MODULE_ID)

-- temperature inside
luup.variable_set(VC_SID, "VariableName1","Temperature C", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable1", temperatureInside, INSIDE_MODULE_ID)

-- humidity inside
luup.variable_set(VC_SID, "VariableName2","Humidity %", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable2", humidityInside, INSIDE_MODULE_ID)

-- pressure
luup.variable_set(VC_SID, "VariableName3","Pressure hPa", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable3", pressure , INSIDE_MODULE_ID)

-- CO2
luup.variable_set(VC_SID, "VariableName4","CO2 PPM", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable4", co2, INSIDE_MODULE_ID)

-- noise level
luup.variable_set(VC_SID, "VariableName5","Noise Level dB", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable5", noiseLevel, INSIDE_MODULE_ID)

end


– End program

[/code]

Appreciate your help a_lurker, and have made some progress. However, I can't install VXContainer twice, nothing happens? Or do I need to install another device using the install file? I'm guessing at most of all this! Also not sure what to do with the code, do I save that as a D_ file, upload it and link it to a new device? Lastly there are four variables in the code for authentication but Im only aware of two, my userid and password. I'll Google around to try to work it out and reply for others' benefit if I crack it!

You install “Variable Container” just once. Then to create the second “Variable Container” go to UI5–>Apps–>My Apps and click the link “Variable Container” In there you will see a button marked “Create another”.

I’m not sure how Sebastien used this code but I figure you could put it in a scene that is triggered by the scheduler. So that’s UI5–>Automation–>New Scene Set up a Schedule, say every 1/2 hour (or shorter while testing). Click the tab labelled “Luup” and paste the code into there. Don’t forget to save all this as you go along. On the code above you should add this to the end of it

return true

To just test the code, you can use UI5–>Apps–>Develop Apps–>Test Luup code (Lua) Paste in the code with the extra bit I just mentioned. Run it and see what happens.

Tuto :

Merci beaucoup pour le tutoriel captainigloo.

Thank you both for all this, but… When I run the scene it says scene started then does nothing more, and the Vcontainers remain unchanged. When I paste the code into the Test LUA section I get code failed. This is both with and without the return true statement. I will include my code here - the only changes I have made are to remove my user email and password for netatmo.com.


– NAME: netatmo-vera.lua
– AUTHOR: Sebastien Joly
– DATE: 29/01/2013
– COMMENT: Get the data from a Netatmo station
– Requires the use of two Vera VContainer plugins and a JSON library


– Change these values to match the authentication used for your Netatmo account
– You will also need to put in the VContainer IDs further below

local s_client_id = “51c2a5bb187759203d000029”
local s_client_secret = “EfiQ85UIz4D3K32UfK1M4Ee2fGGhOcfQezFz7aylVtKbL”
local s_username = “mynetatmoemailaddress”
local s_password = “mynetatmopassword”


local request_body = “grant_type=password&client_id=” … s_client_id …"&client_secret=" … s_client_secret … “&username=” … s_username … “&password=” … s_password


– Libraries

require ‘ltn12’
require ‘socket.http’

– JSON is not native to Vera. You will need to install a plugin
– that also installs a json library as a side effect / byproduct
– Suggest the Google Calendar plugin be used to do this
json = require(“json”)


– HTTP POST function

function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
url = p_url;
method = “POST”;
headers =
{
[“Content-Type”] = “application/x-www-form-urlencoded”;
[“Content-Length”] = #p_body;
};
source = ltn12.source.string(p_body);
sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end


– Main procedure

reponsepost = posthttp(“https://api.netatmo.net/oauth2/token”,request_body)
access_token = reponsepost.access_token
reponsepost = posthttp(“https://api.netatmo.net/api/devicelist","access_token=” … access_token)

moduleInside = reponsepost.body.devices[1]._id
moduleOutside = reponsepost.body.modules[1]._id

reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … moduleInside … “&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last”)
luup.log ("---------------")

temperatureInside = reponsepost.body[1].value[1][1]
co2 = reponsepost.body[1].value[1][2]
humidityInside = reponsepost.body[1].value[1][3]
pressure = reponsepost.body[1].value[1][4]
noiseLevel = reponsepost.body[1].value[1][5]

luup.log (temperatureInside)
luup.log (co2)
luup.log (humidityInside)
luup.log (pressure)
luup.log (noiseLevel)

reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … moduleInside … “&module_id=” … moduleOutside … “&scale=max&type=Temperature,Humidity&date_end=last”)
temperatureOutside = reponsepost.body[1].value[1][1]
humidityOutside = reponsepost.body[1].value[1][2]

luup.log (temperatureOutside)
luup.log (humidityOutside)
luup.log ("---------------")


– Put the local variables into two VCONTAINER plugins
– Change the device two IDs to match yours

local INSIDE_MODULE_ID = 100 – VContainer ID: inside
local OUTSIDE_MODULE_ID = 104 – VContainer ID: outside

local VC_SID = “urn:upnp-org:serviceId:VContainer1”

if (status == 0) then
local currentTime = os.date("*t")
currentTime = currentTime.hour … “:” … currentTime.min
luup.variable_set(VC_SID, “VariableName3”,“Hour”, OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, “Variable3”, currentTime, OUTSIDE_MODULE_ID)

-- temperature outside
luup.variable_set(VC_SID, "VariableName1","Temperature", OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable1", temperatureOutside, OUTSIDE_MODULE_ID)

-- humidity outside
luup.variable_set(VC_SID, "VariableName2","Humidity", OUTSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable2", humidityOutside, OUTSIDE_MODULE_ID)

-- temperature inside
luup.variable_set(VC_SID, "VariableName1","Temperature C", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable1", temperatureInside, INSIDE_MODULE_ID)

-- humidity inside
luup.variable_set(VC_SID, "VariableName2","Humidity %", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable2", humidityInside, INSIDE_MODULE_ID)

-- pressure
luup.variable_set(VC_SID, "VariableName3","Pressure hPa", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable3", pressure , INSIDE_MODULE_ID)

-- CO2
luup.variable_set(VC_SID, "VariableName4","CO2 PPM", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable4", co2, INSIDE_MODULE_ID)

-- noise level
luup.variable_set(VC_SID, "VariableName5","Noise Level dB", INSIDE_MODULE_ID)
luup.variable_set(VC_SID, "Variable5", noiseLevel, INSIDE_MODULE_ID)

end

return true


– End program

Have you a json library installed?

On the “Code Failed” - install infoviewer (search forum), so you can easily view the log file and then report back on what line failed by examining the log file, when you run the program in the Lua test area.

Are you sure you are getting valid data back from posthttp ?
You have no checks of the return status … You assume everything is correct.

I did not verify … do you have to url encode before calling socket.http.request ?
If so, the @ in your email address will have to be encoded … I am not sure if you have any special characters in your password.

Thank you both. No, the @ is not encoded, I have no idea how to do that! Netatmo does use an email address as the use rid so anyone using this code will have to do the same. May I ask how to do so? The original code just had xxxxxx so I replaced that with my email address. In my case my password is upper and lower case letters and numerical so I guess that’s ok. I will go off now and look up info view. And Richard, i agree about the error checking, if it was my code i would do so, but my programming stopped with Assembler/machine code on IBM Mainframes over twenty years ago!

Thanks again, Rob

There are websites that will do this for you.

See: http://meyerweb.com/eric/tools/dencoder/
Enter your string and click encode.

@RTS thank you, I now have %40 instead of @ but still errors.

@a_lurker, I’ve installed info viewer and can see the vera logs, but at the time(stamp) that I run the scene including the lua code there is nothing recognisable in the log. Any ideas what I should look for? Sorry to be a nuisance, but its all new to me and I feel a bit dumb!

Try running the code in the the Lua test area:

UI5–>Apps–>Develop Apps–>Test Luup code (Lua)

That will give more information in the log. You should see the code listed in the log and at the start of that, an error message containing the line on which the error occurred, should be shown. Don’t forget to add “return true” to the end of the code.

Hi.

Got it working after a lot of fidelling.
The english version gave faults from all the spaces plus something was wrong in the output to the Vcontainer so I abandoned it.
In the end I also installed the “Google calendar switch” sins i couldn’t get the “json.lua” downloaded in the SSH terminal to work (acc. to the Tuto).

This is the code i used, its the french version but with english words in the Vcontainers. Don’t forget to edit the Vcontainers id numbers (row 70 & 71).

------------------------------------------------------------------------
-- NAME: netatmo-vera.lua
-- AUTHOR: S?bastien Joly
-- DATE  : 29/01/2013
-- COMMENT: Collecter les donn?es d'une station Netatmo
------------------------------------------------------------------------
-- MODIFIER LES ELEMENTS D'AUTHENTIFICATION PAR VOS DONNEES
------------------------------------------------------------------------
local s_client_id = "your netatmo code"
local s_client_secret = "your netatmo code"
local s_username = "yor email with @"
local s_password = "your password"
------------------------------------------------------------------------
local request_body = "grant_type=password&client_id=" .. s_client_id .."&client_secret=" .. s_client_secret .. "&username=" .. s_username .. "&password=" .. s_password
------------------------------------------------------------------------
-- LIBRAIRIES
------------------------------------------------------------------------
require 'ltn12'
require 'socket.http'
json = require("json")-- PAS NATIF SUR LA VERA
------------------------------------------------------------------------
-- FONCTION HTTP POST
------------------------------------------------------------------------
function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
  url = p_url;
  method = "POST";
  headers =
  {
    ["Content-Type"] = "application/x-www-form-urlencoded";
    ["Content-Length"] = #p_body;
  };
  source = ltn12.source.string(p_body);
  sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end
------------------------------------------------------------------------
-- PROCEDURE
------------------------------------------------------------------------
reponsepost = posthttp("https://api.netatmo.net/oauth2/token",request_body)
access_token = reponsepost.access_token
reponsepost = posthttp("https://api.netatmo.net/api/devicelist","access_token=" .. access_token)
module_interne = reponsepost.body.devices[1]._id
module_externe = reponsepost.body.modules[1]._id
reponsepost = posthttp("https://api.netatmo.net/api/getmeasure","access_token=" ..access_token .."&device_id=" .. module_interne .. "&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last")
luup.log ("---------------")
temperature_interieure =reponsepost.body[1].value[1][1]
co2 =reponsepost.body[1].value[1][2]
humidite_interne =reponsepost.body[1].value[1][3]
pression =reponsepost.body[1].value[1][4]
bruit =reponsepost.body[1].value[1][5]
luup.log(temperature_interieure)
luup.log (co2)
luup.log (humidite_interne)
luup.log (pression)
luup.log (bruit)
reponsepost = posthttp("https://api.netatmo.net/api/getmeasure","access_token=" ..access_token .."&device_id=" .. module_interne .. "&module_id=" .. module_externe .. "&scale=max&type=Temperature,Humidity&date_end=last")
temperature_externe =reponsepost.body[1].value[1][1]
humidite_externe =reponsepost.body[1].value[1][2]
luup.log(temperature_externe)
luup.log (humidite_externe)
luup.log ("---------------")
------------------------------------------------------------------------
-- CHARGEMENT DES VARIABLES LOCALES DANS LES DEUX VCONTAINER
------------------------------------------------------------------------
local SID_Vc = "urn:upnp-org:serviceId:VContainer1"
local ID_modint = 123 -- Indoor container ID replace 123
local ID_modext = 124 -- Outdoor container ID replace 124
local currentTime = os.date("%X")
-- currentTime
      luup.variable_set(SID_Vc, "VariableName3","Time", ID_modext)
         luup.variable_set(SID_Vc, "Variable3", os.date("%X"), ID_modext)
-- temperature exterieure
      luup.variable_set(SID_Vc, "VariableName1","Temp ?C", ID_modext)
         luup.variable_set(SID_Vc, "Variable1", temperature_externe, ID_modext)
-- humidite exterieure
      luup.variable_set(SID_Vc, "VariableName2","Humidity %", ID_modext)
         luup.variable_set(SID_Vc, "Variable2", humidite_externe, ID_modext)
-- temperature interieure
        luup.variable_set(SID_Vc, "VariableName1","Temp ?C", ID_modint)
           luup.variable_set(SID_Vc, "Variable1", temperature_interieure, ID_modint)
-- Humidite interieure
      luup.variable_set(SID_Vc, "VariableName2","Humidity %", ID_modint)
         luup.variable_set(SID_Vc, "Variable2", humidite_interne, ID_modint) 
-- Pression
      luup.variable_set(SID_Vc, "VariableName3","mBar", ID_modint)
         luup.variable_set(SID_Vc, "Variable3", pression , ID_modint) 
-- CO?
      luup.variable_set(SID_Vc, "VariableName4","CO2 PPM", ID_modint)
         luup.variable_set(SID_Vc, "Variable4", co2, ID_modint) 
-- Bruit
      luup.variable_set(SID_Vc, "VariableName5","Noise dB", ID_modint)
         luup.variable_set(SID_Vc, "Variable5", bruit, ID_modint) 
------------------------------------------------------------------------
-- FIN
------------------------------------------------------------------------
return true

Put it in a scene and have it scheduled to run every 5 min.

Thanks Captainigloo for sharing the code.

Thanks both. I seem to be close, but still get errors. I have copied and modified your code Ric, the spaces before the clientid wedre a problem, now the code looks OK in the log, when in dev app/test lua, but at the end of the code I get an error:

– Bruit
intl_chrintl_chr intl_chrintl_chr intl_chrintl_chr luup.variable_set(SID_Vc, “VariableName5”,“Noise dB”, ID_modint)
intl_chrintl_chr intl_chrintl_chr intl_chrintl_chr intl_chrintl_chr intl_chrintl_chrluup.variable_set(SID_Vc, “Variable5”, bruit, ID_modint)

– FIN

return true <0x30644680>
01 06/24/13 20:17:04.815 ctrl_chr[31;1mLuaInterface::LoadCode: [string “---------------------------------------------------------------…”]:28: unexpected symbol near 'intl_chr’ctrl_chr[0m <0x30644680>
01 06/24/13 20:17:04.830 ctrl_chr[31;1mJobHandler_LuaUPnP::RunLua failed: ------------------------------------------------------------------------

The lines after the return true line are in red in the log. Of course, the Vcontainers are unchanged if I run this code without the return true statement inside the scene lua. Hoping you can educate me!

Cheers, Rob

In infoviewer - when you see intl_chr it means a symbol greater than 7F hex has been found. They shouldn’t be in the code. Indicates some sort of internationalisation problem - where are you people? Have a read of this just in case:

http://forum.micasaverde.com/index.php/topic,12857.msg115967.html#msg115967

Couple of other minor problems - this code contains semicolons, which is incorrect. They should be commas and there are a couple of extras.

{ url = p_url; method = "POST"; headers = { ["Content-Type"] = "application/x-www-form-urlencoded"; ["Content-Length"] = #p_body; }; source = ltn12.source.string(p_body); sink = ltn12.sink.table(response_body); }

Plus a few of the variables are not declared ‘local’ - for example:

temperature_interieure =reponsepost.body[1].value[1][1] co2 =reponsepost.body[1].value[1][2] humidite_interne =reponsepost.body[1].value[1][3] pression =reponsepost.body[1].value[1][4] bruit =reponsepost.body[1].value[1][5]

I have attached another version that may improve things = please test with your account details etc in the Luup test area and report any log errors.

EDIT - Version 3 now attached.

[quote=“captainigloo, post:1, topic:174148”]Here is a LUA script to collect data from the REST API Netatmo to my Vera. At the moment a single script pushes all the data in a Vcontainer.

http://forum.netatmo.com/viewtopic.php?f=5&t=1026&sid=ddb92e4b8e5fbd371c15d0e30deec1ee
http://www.touteladomotique.com/forum/viewtopic.php?f=48&t=9905&p=80350#p80350

[code]

– NAME: netatmo-vera.lua
– AUTHOR: S?bastien Joly
– DATE : 29/01/2013
– COMMENT: Collecter les donn?es d’une station Netatmo

– MODIFIER LES ELEMENTS D’AUTHENTIFICATION PAR VOS DONNEES

local s_client_id = “XXXXXX”
local s_client_secret = “XXXXXX”
local s_username = “XXXXXX”
local s_password = “XXXXXX”

local request_body = “grant_type=password&client_id=” … s_client_id …"&client_secret=" … s_client_secret … “&username=” … s_username … “&password=” … s_password

– LIBRAIRIES

require ‘ltn12’
require ‘socket.http’
json = require(“json”)-- PAS NATIF SUR LA VERA

– FONCTION HTTP POST

function posthttp(p_url,p_body)
local response_body = { }
local res, code, response_headers = socket.http.request
{
url = p_url;
method = “POST”;
headers =
{
[“Content-Type”] = “application/x-www-form-urlencoded”;
[“Content-Length”] = #p_body;
};
source = ltn12.source.string(p_body);
sink = ltn12.sink.table(response_body);
}
return json.decode(table.concat(response_body),true)
end

– PROCEDURE

reponsepost = posthttp(“https://api.netatmo.net/oauth2/token”,request_body)
access_token = reponsepost.access_token
reponsepost = posthttp(“https://api.netatmo.net/api/devicelist","access_token=” … access_token)
module_interne = reponsepost.body.devices[1]._id
module_externe = reponsepost.body.modules[1]._id
reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … module_interne … “&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last”)
luup.log ("---------------")
temperature_interieure =reponsepost.body[1].value[1][1]
co2 =reponsepost.body[1].value[1][2]
humidite_interne =reponsepost.body[1].value[1][3]
pression =reponsepost.body[1].value[1][4]
bruit =reponsepost.body[1].value[1][5]
luup.log(temperature_interieure)
luup.log (co2)
luup.log (humidite_interne)
luup.log (pression)
luup.log (bruit)
reponsepost = posthttp(“https://api.netatmo.net/api/getmeasure","access_token=” …access_token …"&device_id=" … module_interne … “&module_id=” … module_externe … “&scale=max&type=Temperature,Humidity&date_end=last”)
temperature_externe =reponsepost.body[1].value[1][1]
humidite_externe =reponsepost.body[1].value[1][2]
luup.log(temperature_externe)
luup.log (humidite_externe)
luup.log ("---------------")

– CHARGEMENT DES VARIABLES LOCALES DANS LES DEUX VCONTAINER

local SID_Vc = “urn:upnp-org:serviceId:VContainer1”
local ID_modint = 34 – pour ma vera Module int?rieur VC ID #34
local ID_modext = 35 – pour ma vera Module ext?rieur VC ID #35
if (status == 0) then
local currentTime = os.date("*t")
currentTime = currentTime.hour … “:” … currentTime.min
luup.variable_set(SID_Vc, “VariableName3”,“Heure”, ID_modext)
luup.variable_set(SID_Vc, “Variable3”, currentTime, ID_modext)
– temperature exterieure
luup.variable_set(SID_Vc, “VariableName1”,“Temp?rature”, ID_modext)
luup.variable_set(SID_Vc, “Variable1”, temperature_externe, ID_modext)
– humidite exterieure
luup.variable_set(SID_Vc, “VariableName2”,“Humidit?”, ID_modext)
luup.variable_set(SID_Vc, “Variable2”, humidite_externe, ID_modext)
– temperature interieure
luup.variable_set(SID_Vc, “VariableName1”,“Temp?rature ?C”, ID_modint)
luup.variable_set(SID_Vc, “Variable1”, temperature_interieure, ID_modint)
– Humidite interieure
luup.variable_set(SID_Vc, “VariableName2”,“Humidit? %”, ID_modint)
luup.variable_set(SID_Vc, “Variable2”, humidite_interne, ID_modint)
– Pression
luup.variable_set(SID_Vc, “VariableName3”,“Pression Hpa”, ID_modint)
luup.variable_set(SID_Vc, “Variable3”, pression , ID_modint)
– CO?
luup.variable_set(SID_Vc, “VariableName4”,“CO2 PPM”, ID_modint)
luup.variable_set(SID_Vc, “Variable4”, co2, ID_modint)
– Bruit
luup.variable_set(SID_Vc, “VariableName5”,“Bruit db”, ID_modint)
luup.variable_set(SID_Vc, “Variable5”, bruit, ID_modint)
end

– FIN

[/code][/quote]

Is there a way to convert the units from metric to the US system? The Netatmo webapp reports in ?F and mmHg if “US system” is selected in the user account preferences. Thank you for sharing the code.

@a_lurker - Genius! Sort of… and thank you, but… In test mode I now get “Message sent successful” which is a first. In scene execution, I no longer get error messages, but the Vcontainers (I updated the code to my device numbers) are still uninitialised. Two things: should I have return true in the scene lua or was that just for testing? And secondly, do I need to copy the variable names from the code into the containers as a part of the install? So close yet so far…! Much appreciate your help. I am in New Zealand, and there should be no internationalisation issues, however the code was written in France, so maybe that was it?

I had a look further - the original code has been changed of late, to remove this - (see the code previously posted by Ric):

if (status == 0) then ... more stuff .... end

I have it removed from the file attached above to match. So try Version three above.

No you don’t have to manually initialise the VContainer(s). The change of code above explains why you saw nothing change in the containers, as the variable ‘status’ was undefined. Regardless you should still have seen the Netatmo values listed in the log file.

On the ‘return true’. It’s required in the test area but in the scene, it can be ‘return true’ or ‘return false’. If the latter, the actual scene is not entered, otherwise it is (the Lua code is part of the triggering process). But the scene is probably not doing anything eg like turning alight on or off, so it doesn’t matter. Hope that makes sense.

As Richard has pointed out, the code always assumes that the URL returns valid data, in that is no built in error handling of the URL results.