Aller au contenu

Problème Avec Json.decode En V4


fredo

Messages recommandés

Hello, 

je voulais remettre en place une sonde virtuelle basée sur les infos WEATHER.COM

ça fonctionnait en V3.59.

J'ai importé mon périphérique virtuel avec le code suivant et ça ne fonctionne pas.

Quelqu'un a une idée?

HC2 = Net.FHttp("HTTP://wxdata.weather.com")response = HC2:GET("/wxdata/weather/local/FRXX0076?cc=*&unit=m")
-- enregistrement du retour de l API dans une table
response = json.decode(response)
fibaro:setGlobal("WEATHERTMP", response.tmp)
fibaro:setGlobal("WEATHERHMID", response.hmid)  
Lien vers le commentaire
Partager sur d’autres sites

Je switch donc notre conversation ici ;) . Pour résumer:  wxdata.weather.com retourne du xml et pas du json c'est le problème ici.

 

Je regarde un truc simple pour te sortir tmp et hmid sans utiliser un pseudo parser XML...

Lien vers le commentaire
Partager sur d’autres sites

merci, le truc c'est que je voulais aussi récupérer les autres infos (pression, vitesse du vent,...)

et je viens de trouver un post sur "parser xml" : http://www.domotique-fibaro.fr/index.php/topic/2128-parser-xml/

ça n'a pas l'air simple !!!

Lien vers le commentaire
Partager sur d’autres sites

Oui pas la peine de faire une usine àgaz :D

local HC2 = Net.FHttp("wxdata.weather.com");
local result, status, errorCode = HC2:GET("/wxdata/weather/local/FRXX0076?cc=*&unit=m");
if tonumber(status) == 200 then
  if (result ~= nil) then
    local temp = tonumber(result:match("<tmp>(.+)</tmp>") or 0);
    local hmid = tonumber(result:match("<hmid>(.+)</hmid>") or 0);
    fibaro:debug(temp.."°C");
    fibaro:debug(hmid.."%");
  end
else
  fibaro:debug("Error Code: " .. errorCode);
end

le debug:

[DEBUG] 23:31:52: 8°C
[DEBUG] 23:31:52: 91%

Tu as des questions ?

Lien vers le commentaire
Partager sur d’autres sites

Hum, je suis dans le coin en ce moment, mais pas mal occupé.... normalement dans 2 semaines ça sera calme, je t'en reparle :77:

Sinon y'a Latoupie dans ton coin la semaine prochaine.

 

Bon sinon sérieusement je laisse Krikroff reprendre la main, car ta demande est un peu trop pointue pour moi.

Lien vers le commentaire
Partager sur d’autres sites

Re....

 

 

si je veux récupérer aussi des chaines de caractères et stocker tout ça dans des variables globales, ça se passe comment ?

local HC2 = Net.FHttp("wxdata.weather.com");
local result, status, errorCode = HC2:GET("/wxdata/weather/local/FRXX0076?cc=*&unit=m");
if tonumber(status) == 200 then
  if (result ~= nil) then
    local temp = tonumber(result:match("<tmp>(.+)</tmp>") or 0);
    local hmid = tonumber(result:match("<hmid>(.+)</hmid>") or 0);
    fibaro:debug(temp.."°C");
    -- Enregistrement de tmp dans la vg WEATHERTMP
    fibaro:setGlobal("WEATHERTMP", tmp);
    fibaro:debug(hmid.."%");
    -- Enregistrement de hmiddans la vg WEATHERHMID
    fibaro:setGlobal("WEATHERHMID", hmid) 
  end
else
  fibaro:debug("Error Code: " .. errorCode);
end

et pour utiliser la variable globale c'est

local tmp = fibaro:getGlobalValue("WEATHERTMP");
fibaro:debug(tmp);
Lien vers le commentaire
Partager sur d’autres sites

Soit tu enlèves les tonumber soit tu laisse setGlobal faire tranquillement un CAST et passer la valeur en string, soit tu fais un tostring.... Ce n'est pas les solutions qui manquent

Tu veux que je modifie le code entre midi et deux ?

JC

Envoyé de mon smartphone

Lien vers le commentaire
Partager sur d’autres sites

mince j'ai pas vu ton message. :(

Si tu peux me donner un exemple pour "cloudy" à  stocker dans METEO, après j'adapterai.

Merci. 

;)

 

<cc>

<lsup>2/26/15 8:05 AM CET</lsup>
<obst>Paris-Montsouris, 75, FR</obst>
<tmp>7</tmp>
<flik>5</flik>
<t>Cloudy</t>
Lien vers le commentaire
Partager sur d’autres sites

Bonjour

pour ma part je récupère des données d'un PHP sur mon serveur

et sur mon Module j'ai ce format qui marchait avant de passer en 3.6 et que j'aimerais également faire marcher en plus de la 3.6 en V4

HC2 = Net.FHttp("xxxx.fr")
response = HC2:GET("/xxxx/agenda-WITHINGS-HIER.php?cal=xxxxxxxxxxxxxxxxxxxxgroup.calendar.google.com/private-xxxxxxxxxxxxxxxx&decode=0&defaut=0,Poids&json=1")  -- 0,NO_DATA,
response = json.decode(response)
fibaro:setGlobal("WITHINGS", response.WITHINGS)
fibaro:setGlobal("WITHINGS_Text", response.WITHINGS_text)
fibaro:log("WITHINGS_ : "..fibaro:getGlobalValue("WITHINGS_Text"))
fibaro:call(206,"setProperty","ui.Label2.value",response.WITHINGS_text)

en message j'obtiens

[ERROR] 09:44:03: line 10: Expected value but found invalid token at character 1

Avez-vous une idée ?

Lien vers le commentaire
Partager sur d’autres sites

@Fredo,

 

Je m'excuse pour mon retour très très tardif ... Et pour me faire pardonner je te propose 1 solution plus propre :)  car la récupération de t pose des problèmes en effet il y a 3 ou 4 node t dans le code...

 

Voici un parser XML

---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
-- LUA XML parser
-- UPDATE: Jean-Christophe Vermandé
-- NOTE: This is a modified version of Alexander Makeev's Lua-only XML parser
-- found here: http://lua-users.org/wiki/LuaXml
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
Parser = function()
    XmlParser = {};
    function XmlParser:ToXmlString(value)
        value = string.gsub(value, "&", "&".."amp;"); -- '&' -> "&"
        value = string.gsub(value, "<", "&".."lt;"); -- '<' -> "<"
        value = string.gsub(value, ">", "&".."gt;"); -- '>' -> ">"
        value = string.gsub(value, "\"", "&".."quot;"); -- '"' -> """
        value = string.gsub(value, "([^%w%&%;%p%\t% ])",
            function(c)
                return string.format("%X;", string.byte(c))
            end);
        return value;
    end

    function XmlParser:FromXmlString(value)
        value = string.gsub(value, "([%x]+)%;",
            function(h)
                return string.char(tonumber(h, 16))
            end);
        value = string.gsub(value, "([0-9]+)%;",
            function(h)
                return string.char(tonumber(h, 10))
            end);
        value = string.gsub(value, "&".."quot;", "\"");
        value = string.gsub(value, "&".."apos;", "'");
        value = string.gsub(value, "&".."gt;", ">");
        value = string.gsub(value, "&".."lt;", "<");
        value = string.gsub(value, "&".."amp;", "&");
        return value;
    end

    function XmlParser:ParseArgs(node, s)
        string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a)
            node:addProperty(w, self:FromXmlString(a))
        end)
    end

    function XmlParser:ParseXmlText(xmlText)
        local stack = {}
        local top = newNode()
        table.insert(stack, top)
        local ni, c, label, xarg, empty
        local i, j = 1, 1
        while true do
            ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
            if not ni then break end
      		--fibaro:debug("label: "..label);
      		--fibaro:debug("xarg: "..xarg);
            local text = string.sub(xmlText, i, ni - 1);      		
            if not string.find(text, "^%s*$") then
                local lVal = (top:value() or "") .. self:FromXmlString(text)
        		--fibaro:debug(lVal);
                stack[#stack]:setValue(lVal)
            end
            if empty == "/" then -- empty element tag
                local lNode = newNode(label);        		
                self:ParseArgs(lNode, xarg)
                top:addChild(lNode)
            elseif c == "" then -- start tag
                local lNode = newNode(label);
                self:ParseArgs(lNode, xarg)
                table.insert(stack, lNode)
        		top = lNode
            else -- end tag
                local toclose = table.remove(stack) -- remove top
                top = stack[#stack]
                if #stack < 1 then
                    error("XmlParser: nothing to close with " .. label)
                end
                if toclose:name() ~= label then
                    error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
                end
                top:addChild(toclose)
            end
            i = j + 1
        end
        local text = string.sub(xmlText, i);
        if #stack > 1 then
            error("XmlParser: unclosed " .. stack[#stack]:name())
        end
        return top
    end
    return XmlParser
end

newNode = function(name)
  local node = {}
  node.___value = nil
  node.___name = name
  node.___children = {}
  node.___props = {}
  
  function node:value() return self.___value end
  function node:setValue(val) self.___value = val end
  function node:name() return self.___name end
  function node:setName(name) self.___name = name end
  function node:children() return self.___children end
  function node:numChildren() return #self.___children end
  function node:addChild(child)
    if self[child:name()] ~= nil then
      if type(self[child:name()].name) == "function" then
        local tempTable = {}
        table.insert(tempTable, self[child:name()])
        self[child:name()] = tempTable
      end
      table.insert(self[child:name()], child)
    else
      self[child:name()] = child
    end
    table.insert(self.___children, child)
  end
  
  function node:properties() return self.___props end
  function node:numProperties() return #self.___props end
  function node:addProperty(name, value)
    local lName = "@" .. name
    if self[lName] ~= nil then
      if type(self[lName]) == "string" then
        local tempTable = {}
        table.insert(tempTable, self[lName])
        self[lName] = tempTable
      end
      table.insert(self[lName], value)
    else
      self[lName] = value
    end
    table.insert(self.___props, { name = name, value = self[name] })
  end  
  return node
end

Puis le code pour l'utiliser dans notre cas

local HC2 = Net.FHttp("wxdata.weather.com");
local result, status, errorCode = HC2:GET("/wxdata/weather/local/FRXX0076?cc=*&unit=m");
if tonumber(status) == 200 then
  if (result ~= nil) then
    local xml = Parser();
    local parsedXml = xml:ParseXmlText(result);
    local parsedDIDL = parsedXml['weather'];
    local cnt = 1;
    if parsedDIDL ~= nil then
      local children = parsedDIDL["cc"] or {};
      fibaro:debug(tostring(children.obst:value()));
      fibaro:debug(tostring(children.tmp:value()));
      fibaro:debug(tostring(children.t:value()));
      fibaro:debug(tostring(children.hmid:value()));
    else
      error("Node not created")
    end
  end
else
  fibaro:debug("Error Code: " .. errorCode);
end
  • Upvote 1
Lien vers le commentaire
Partager sur d’autres sites

donc j'ai essayé et ça fonctionne.

par contre, si je veux récupérer la pression contenue dans "r" qui est dans une sous-section "bar" de "cc", ça se passe comment?

 

<cc>

<lsup>3/02/15 10:25 PM CET</lsup>
<obst>Paris-Montsouris, 75, FR</obst>
<tmp>6</tmp>
<flik>5</flik>
<t>Clear</t>
<icon>31</icon>
<bar>
<r>1020.32</r>
<d>steady</d>
</bar>
<wind>
<s>8</s>
<gust>N/A</gust>
<d>220</d>
<t>SW</t>
</wind>
<hmid>55</hmid>
<vis>16.1</vis>
<uv>
<i>0</i>
<t>Low</t>
</uv>
<dewp>-2</dewp>
<moon>
<icon>12</icon>
<t>Waxing Gibbous</t>
</moon>
</cc>
Lien vers le commentaire
Partager sur d’autres sites

×
×
  • Créer...