通过 NodeMCU 上的 API 仅获取 JSON 的部分信息

我正在使用 http.get() 从一个 API 中获取 JSON 数据,但是无法获取到数据。我怀疑这个 JSON 对于 NodeMCU 来说太大了。我只需要子部分"stats:"中的信息。是否可能仅从 JSON 获取该部分?

编辑:

这是我的代码

function getstats()
http.get("https://api.aeon-pool.com/v1/stats_address?address=WmsGUrXTR7sgKmHEqRNLgPLndWKSvjFXcd4soHnaxVjY3aBWW4kncTrRcBJJgUkeGwcHfzuZABk6XK6qAp8VmSci2AyGHcUit", nil, function(code, pool)
        if (code < 0) then
            print("无法获取状态")
        else
            h = cjson.decode(pool)
            hashrate = h[1]["hashrate"]
            print(hashrate)
            dofile('update_display.lua')
        end
    end)
end

我还有另一个从另一个 API 中获取数据的函数

function getaeonrate()
http.get("https://api.coinmarketcap.com/v1/ticker/aeon/?convert=EUR", nil, function(code, dataaeon)
   if (code < 0) then
      print("无法获取 aeon")
   else
      -- 解码 JSON 数据
      m = cjson.decode(dataaeon)
      -- 从解码的 JSON 中提取 AEON/EUR 价格
      aeonrate = string.format("%f", m[1]["price_eur"]);
      aeonchange = "24小时 " .. m[1]["percent_change_24h"] .. "% 7d " .. m[1]["percent_change_7d"] .. "%"
      dofile('update_display.lua')
      end
  end)
end

但现在奇怪的事情是,当我想从 getstats() 中访问'pool' 时,我得到的是从 getaeonrate() 中获取的 JSON 数据。所以"hashrate"并不在 JSON 中,因为我正在从另一个函数中获取 JSON。

我尝试了只使用 getstats() 的新项目,但总是出现以下错误

HTTP client: Disconnected with error: -9
HTTP client: Connection timeout
HTTP client: Connection timeout

昨天我认为来自 api.aeon-pool.com 的响应太大了,如果您在 Web 浏览器中查看 JSON,则可以看到顶部条目是 'stats:',我只需要该部分数据,而不需要其他任何东西。因此,如果请求太大,只需从 JSON 中获取该部分即可,这就是我最初的问题。现在我甚至不确定有什么地方没有正确工作,我读到 NodeMCU 固件通常存在与 http.get() 相关的问题,并且很长时间都无法正确工作,但是从 api.coinmarketcap.com 获取数据在原始项目中工作正常。

点赞
用户131929
用户131929

HTTP 模块的问题几乎可以肯定与 https://github.com/nodemcu/nodemcu-firmware/issues/1707 (SSL 和 HTTP 存在问题) 相关。

因此,我尝试使用当前主分支上的更基本的 TLS 模块。这意味着您需要手动解析 HTTP 响应,包括所有标头,以查找 JSON 内容。此外,您似乎正在使用较旧的 NodeMCU 版本,因为您仍在使用 CJSON - 在下面我使用了 SJSON:

当前 NodeMCU 主分支

function getstats()
  buffer = nil
  counter = 0
  local srv = tls.createConnection()
  srv:on("receive", function(sck, payload)
    print("[stats] received data, " .. string.len(payload))
    if buffer == nil then
      buffer = payload
    else
      buffer = buffer .. payload
    end
    counter = counter + 1

    -- not getting HTTP content-length header back -> poor man's checking for complete response
    if counter == 2 then
      print("[stats] done, processing payload")
      local beginJsonString = buffer:find("{")
      local jsonString = buffer:sub(beginJsonString)
      local hashrate = sjson.decode(jsonString)["stats"]["hashrate"]
      print("[stats] hashrate from aeon-pool.com: " .. hashrate)
    end
  end)
  srv:on("connection", function(sck, c)
    sck:send("GET /v1/stats_address?address=WmsGUrXTR7sgKmHEqRNLgPLndWKSvjFXcd4soHnaxVjY3aBWW4kncTrRcBJJgUkeGwcHfzuZABk6XK6qAp8VmSci2AyGHcUit HTTP/1.1\r\nHost: api.aeon-pool.com\r\nConnection: close\r\nAccept: */*\r\n\r\n")
  end)
  srv:connect(443, "api.aeon-pool.com")
end

请注意,receive 事件会为每个网络帧触发: https://nodemcu.readthedocs.io/en/latest/en/modules/net/#netsocketon

NodeMCU 无法与 api.coinmarketcap.com 建立连接,原因是 TLS 握手失败。不知道为什么。否则,您的 getaeonrate() 可以实现类似的功能。

Frozen 1.5.4 分支

在旧分支上,net 模块可以连接到 coinmarketcap.com。

function getaeonrate()
  local srv = net.createConnection(net.TCP, 1)
  srv:on("receive", function(sck, payload)
    print("[aeon rate] received data, " .. string.len(payload))
    local beginJsonString = payload:find("%[")
    local jsonString = payload:sub(beginJsonString)
    local json = cjson.decode(jsonString)
    local aeonrate = string.format("%f", json[1]["price_eur"]);
    local aeonchange = "24h " .. json[1]["percent_change_24h"] .. "% 7d " .. json[1]["percent_change_7d"] .. "%"
    print("[aeon rate] aeonrate from coinmarketcap.com: " .. aeonrate)
    print("[aeon rate] aeonchange from coinmarketcap.com: " .. aeonchange)
  end)
  srv:on("connection", function(sck, c)
    sck:send("GET /v1/ticker/aeon/?convert=EUR HTTP/1.1\r\nHost: api.coinmarketcap.com\r\nConnection: close\r\nAccept: */*\r\n\r\n")
  end)
  srv:connect(443, "api.coinmarketcap.com")
end

结论

  • 由于固件错误(1707),HTTP 模块和 TLS 看起来不适用于您的 API。
  • 当前主分支的 net/TLS 模块设法连接到 api.aeon-pool.com,但无法连接到 api.coinmarketcap.com。
  • 对于旧的冻结的 1.5.4 分支,情况恰好相反。
  • 可能存在固件和 API 提供者之间不匹配的加密套件问题。

-> :( 不太好。

2017-12-25 22:36:23