This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Scripting: Request via API and JSON format file processing
#1
Hello,

I am reaching out to you because I would like to create a Lua script on my Wyser for KNX (Schneider) to make a request to capture the outdoor temperature from my weather station via the Ecowitt website. Ecowitt provides an API for making such requests. I tried to set it up directly on the machine, but I couldn't make it work.

As a result, I ran a script on my PC running Linux because it's easier to use the standard output. To make it work, I had to install additional packages: lua-socket, lua-socket, lua-socket. Below is the script that works on my PC (except the KNX part at the bottom) but does not work on the LogicMachine.

Now, I am facing a portability issue to this KNX supervisor. Could someone help me? I believe I am not very far from achieving my goal.

Thank you in advance.

NiSAGNEL


Code:
--I left in comments what was useful to me for development on my PC
json = require('json')
ltn12 = require('ltn12')
https = require('ssl.https')
-- Extraire les variables de l'URL
local applicationKey = 'MyApplication-Key'
local apiKey = 'MyAPI-Key'
local MacAdd = 'Mon Adresse MAC'
local TempUnit = '1' -- Temperature Unit 1 = °C
local Research = 'outdoor.temperature'
-- URL complète avec les paramètres
local url = 'https://api.ecowitt.net/api/v3/device/real_time?application_key=' .. applicationKey .. '&api_key=' .. apiKey .. '&mac=' .. MacAdd .. '&temp_unitid=' .. TempUnit .. '&call_back=' .. Research
-- Tableau pour stocker la réponse HTTP
local resp = {}
-- Effectuer la requête HTTPS
local res, code, headers, status = https.request{
  url = url,
  method = 'GET',
  sink = ltn12.sink.table(resp),
}
-- Variable pour les erreurs de requetes
local LocalCountError = '1'
-- Afficher le code de statut et la réponse brute pour le débogage
-- print("Code de statut:", code)
-- print("Réponse brute:", table.concat(resp))
-- Vérifier le code de statut de la réponse
if code == 200 then
  -- Concaténer la réponse HTTP
  resp = table.concat(resp)
  -- Décoder la réponse JSON
  local data = json.decode(resp)
  -- Afficher la réponse JSON brute pour le débogage
  -- print("Raw JSON response:", resp)
  -- Vérifier si la réponse est un objet JSON valide
  if data then
    -- Vérifier si le champ 'msg' est 'success'
    if data.msg == "success" then
      -- Extraire la valeur de la température
      local tempExt = tonumber(data.data.outdoor.temperature.value)
      if tempExt then
        -- print(Research .. " : " .. tempExt .. " ℃")
        LocalCountError = '0'
      else
        -- print("Impossible d'extraire la température.")
        LocalCountError = LocalCountError + 1
      end
    else
      -- print("Erreur dans la réponse JSON : " .. data.msg)
      LocalCountError = LocalCountError + 10
    end
  else
    -- print("Réponse JSON invalide.")
    LocalCountError = LocalCountError + 100
  end
else
  print("La requête HTTPS a échoué. Code de statut : " .. code)
  LocalCountError = LocalCountError + 1000
end
-- Error Management
-- Read Error on KNX address
local Error = tonumber(grp.read('32/3/254')) or 999
if LocalCountError ~= 0 then
  Error = Error + 1
  if Error > 5 then
    tempExt = '99'
  end
else
    Error = 0
end
-- Send to KNX Address Error
grp.write('32/3/254', Error)
-- Send to KNX Address Valeur de Température
grp.write('32/3/1', tempExt)
Reply
#2
Hello,
I found a way to make my script verbose to better understand what is happening by redirecting messages to the logs.
After the HTTPS request, I inserted the following line of code:
Code:
log("Status code:", code)
And the output is as follows:
Code:
* arg: 1
  * string: Status code:
* arg: 2
  * string: wantread
The variable "code," which works on my PC by returning the value 200, gives me the value "104" when the script runs on the Wiser for KNX. Information online suggests updating libraries such as ssl.https, json, etc. I believe we may need to wait for a future firmware update. I will keep you informed if I manage to get my script working.

Thank you,
NiSAGNEL
Reply
#3
Hello,

I had misunderstood... regarding my issue. Upon checking, I realized that my firewall was not allowing traffic from WISER for KNX to the Ecowitt site. I am updating the code; someone might find it useful or improve it.
This code allows querying the Ecowitt site through APIs with the purpose of acquiring the value from a temperature sensor.
NiSAGNEL

Code:
json = require('json')
ltn12 = require('ltn12')
https = require('ssl.https')
--Déclaration Variable erreur
local LocalCountError = tonumber(0)
LocalCountError = 0
-- Read Error on KNX address
local Error = tonumber(grp.read('32/3/254')) or 2

-- Extraire les variables de l'URL
local applicationKey = 'MyApplication-Key'
local apiKey = 'MyAPI-Key'
local MacAdd = 'My MAC Adresse'
local TempUnit = '1' -- Temperature Unit 1 = °C
local Research = 'outdoor.temperature'

-- URL complète avec les paramètres
local url = 'https://api.ecowitt.net/api/v3/device/real_time?application_key=' .. applicationKey .. '&api_key=' .. apiKey .. '&mac=' .. MacAdd .. '&temp_unitid=' .. TempUnit .. '&call_back=' .. Research

-- Tableau pour stocker la réponse HTTP
local resp = {}


-- Effectuer la requête HTTPS
local res, code, headers, status = https.request{
  url = url,
  method = 'GET',
  sink = ltn12.sink.table(resp),
}

-- Vérifier le code de statut de la réponse
if code == 200 then
  -- Concaténer la réponse HTTP
  resp = table.concat(resp)
 
  -- Décoder la réponse JSON
  local data = json.decode(resp)
  -- Vérifier si la réponse est un objet JSON valide
  if data then
    -- Vérifier si le champ 'msg' est 'success'
    if data.msg == "success" then
      -- Extraire la valeur de la température
      -- local tempExt = tonumber(data.data.outdoor.temperature.value)
      local tempExt = string.format("%.2f", data.data.outdoor.temperature.value)
      if tempExt then -- OK
        -- print(Research .. " : " .. tempExt .. " ℃")
        grp.write('32/3/1', tempExt)
        LocalCountError = 0
      else
        -- print("Impossible d'extraire la température.")
        LocalCountError = LocalCountError + 1
      end
    else
      -- print("Erreur dans la réponse JSON : " .. data.msg)
      LocalCountError = LocalCountError + 10
    end
  else
    -- print("Réponse JSON invalide.")
    LocalCountError = LocalCountError + 100
  end
else
  print("La requête HTTPS a échoué. Code de statut : " .. code)
  LocalCountError = LocalCountError + 1000
end

-- Error Management
-- In case of error
if LocalCountError > 0 then
  Error = Error + 1
  if Error > 5 then
    tempExt = '99'
  end
else
  Error = 0
end

-- Send to KNX Address Error
grp.write('32/3/254', Error)


NiSAGNEL
Reply
#4
You should use grp.getvalue() instead of grp.read(). grp.read() only sends a read telegram, it does not return the actual value.
Reply


Forum Jump: