在 NodeMCU 上使用 API 时仅获取 JSON 的一部分

Get only part of a JSON when using an API on NodeMCU

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

编辑:

这是我的代码

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

我还有另一个函数从 getstats()

上面的另一个 api 获取数据
function getaeonrate()
http.get("https://api.coinmarketcap.com/v1/ticker/aeon/?convert=EUR", nil, function(code, dataaeon)
   if (code < 0) then
      print("can't get aeon")     
   else
      -- Decode JSON data
      m = cjson.decode(dataaeon)
      -- Extract AEON/EUR price from decoded JSON
      aeonrate = string.format("%f", m[1]["price_eur"]);
      aeonchange = "24h " .. 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 的响应太大了,如果你在你的网络浏览器中查看 json 你可以看到顶部条目是 'stats:' 我只需要 none 其他东西。因此,如果请求太大,最好只 http.get() json 的那部分,因此我最初的问题。目前我什至不确定是什么不正常,我读到 nodemcu 固件通常在 http.get() 方面有问题并且很长时间都没有正常工作,但是从 api.coinmarketcap.com 在原始项目中工作正常。

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

因此,我尝试在当前主分支上使用 more bare-bone TLS 模块。这意味着您需要手动解析 HTTP 响应,包括所有 headers 以查找 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

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

由于 TLS 握手失败,NodeMCU 无法与 api.coinmarketcap.com 建立连接。不知道为什么会这样。否则你的 getaeonrate() 也可以同样实现。

冰雪奇缘1.5.4分支

使用旧分支,网络模块可以连接到 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 似乎是 no-go。
  • 当前 master 分支的 net/TLS 模块设法连接到 api.aeon-pool.com 但没有连接到 api.coinmarketcap.com.
  • 对于旧的和冻结的 1.5.4 分支,情况正好相反。
  • 固件和 API 提供商之间可能(也)存在不匹配的密码套装问题。

-> :( 没有那样的乐趣