Android & NodeMCU,从服务器接收响应不能正常工作?

Posted

技术标签:

【中文标题】Android & NodeMCU,从服务器接收响应不能正常工作?【英文标题】:Android & NodeMCU, receiving response from server does not work properly? 【发布时间】:2018-08-18 14:01:16 【问题描述】:

我在android 上编写了一个应用程序,它实现了向服务器发送简单的请求(使用Volley)。服务器安装在 NodeMCU (ESP8266) 微控制器上,使用 Lua 编写。问题是,在发送请求后,应用程序并不总是能够打印响应。如果地址是例如“http://www.google.com”它正确发送请求并接收并显示响应,但如果它是下面代码中的地址 - 它正确发送请求(服务器做出反应)但不(?)接收响应(不显示它,显示:“那没有用!”)。您有什么想法吗,我该如何解决它并能够打印响应?

Android(部分负责发送请求):

buttonSynchro.setOnClickListener(new View.OnClickListener() 
    @Override
    public void onClick(View view) 


        // Instantiate the RequestQueue.
        String url = "http://192.168.1.12/";


        // Request a string response from the provided URL.
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() 
                    @Override
                    public void onResponse(String response) 
                        // Display the first 500 characters of the response string.
                        testTextView.setText("Response is: "+ response.substring(0,500));
                    
                , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 
                testTextView.setText("That didn't work!");
            
        );


        // Add the request to the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(SettingsActivity.this);
        queue.add(stringRequest);
    
);  

NodeMCU、Lua:

station_cfg=
station_cfg.ssid="Dom"
station_cfg.pwd="lalala"
wifi.sta.config(station_cfg)
function receive(conn, request)
        print(request)
        print()
        local buf = "";
        buf = buf.."<!doctype html><html>";
        buf = buf.."<h1> ESP8266 Web Server</h1>";
        buf = buf.."</html>";

        conn:send(buf);
        conn:on("sent", function(sck) sck:close() end);     
        collectgarbage();

end

function connection(conn) 
    conn:on("receive", receive) 

end

srv=net.createServer(net.TCP, 30) 
srv:listen(80, connection)

【问题讨论】:

请检查 192.168.1.12 在您的浏览器中是否正常工作。 :-) 是的,当然可以。我以为我已经说过了:) 顺便说一句,您确实没有说它在浏览器中工作,您说服务器“做出反应”,我认为这意味着您看到了打印在 esp 上的请求。 @nPn 是的,我没有直接说。所以说清楚:发送请求后,我看到请求打印在 esp 上,通过浏览器发送请求后,我看到上面显示的 HTML 代码页面。 【参考方案1】:

nPn 的代码适用于某些用户代理(macOS 上的 Chrome/Firfox/curl/wget),但不适用于其他用户代理(macOS 和 ios 上的 Safari,iOS 上的 Firefox Klar)。这可能是由于缺少 HTTP 标头。

我建议您坚持我们在 https://nodemcu.readthedocs.io/en/latest/en/modules/net/#netsocketsend 的文档中提供的示例。

srv = net.createServer(net.TCP)

function receiver(sck, data)
  print(data)
  print()

  -- if you're sending back HTML over HTTP you'll want something like this instead
  local response = "HTTP/1.0 200 OK\r\nServer: NodeMCU on ESP8266\r\nContent-Type: text/html\r\n\r\n"

  response[#response + 1] = "<!doctype html><html>"
  response[#response + 1] = "<h1> ESP8266 Web Server</h1>"
  response[#response + 1] = "</html>"

  -- sends and removes the first element from the 'response' table
  local function send(localSocket)
    if #response > 0 then
      localSocket:send(table.remove(response, 1))
    else
      localSocket:close()
      response = nil
    end
  end

  -- triggers the send() function again once the first chunk of data was sent
  sck:on("sent", send)

  send(sck)
end

srv:listen(80, function(conn)
  conn:on("receive", receiver)
end)

此外,您的代码(以及 nPn 的代码)假设 WiFi 在不应该可用的地方可用。

wifi.sta.config(station_cfg) (with auto-connect=true) and wifi.stat.connect异步,因此是非阻塞的 - 与许多其他 NodeMCU API 一样。因此,您应该将上述代码放入一个函数中,并且只有在设备连接到 AP 并获​​得 IP 后才调用它。您可以通过例如使用 WiFi 事件监视器为 STA_GOT_IP 事件注册回调。您将在https://nodemcu.readthedocs.io/en/latest/en/upload/#initlua 找到一个非常详细的启动序列示例,该示例侦听所有 WiFi 事件。对于初学者,您可能想要修剪此内容并仅监听 got-IP。

【讨论】:

我想补充一点,这些(对我来说)不适用于 Volley 发送请求的方法。但它适用于此处可用的发送请求方法***.com/questions/44377993/…我的问题here中的Lua代码不适用于这两种方法。谢谢。 什么?我很困惑...您接受了答案,即使它对您不起作用? Lua 代码确实 工作,保证。我对答案中提到的所有七个用户代理进行了测试。 我们并没有被对方低估。你的 Lua 代码工作。 Volley 发送请求的方法不起作用(对我来说)(我无法打印响应)。我在上一条评论中发布的链接中提到的发送请求的方法适用于您的 Lua 代码。在我上一条评论中,我并不是说您的 Lua 代码不起作用。也许我应该开始:“Volley 发送请求的方法(对我来说)不适用于这些”。 打印出 Volley 返回的错误也可能会有所帮助。 您的问题是您的 java 回溯中显示的 IndexOutOfBoundsException。您要求子字符串 0 - 500,但响应只有 483 个字符。我将发布一个简单的答案。【参考方案2】:

根据您上面的评论和您发布的显示回溯的link,您的 android 应用程序在 onResponse() 方法中崩溃,因为您要求的子字符串比实际字符串长度长。

您可以通过多种方式解决此问题,但一种方法是将结束索引设置为响应长度和 500 中的最小值(我假设这是您可以在 TextView 中获取的最大值?)。你可以试试改

testTextView.setText("Response is: "+ response.substring(0,500));

testTextView.setText("Response is: "+ response.substring(0, Math.min(response.length(), n)));

或您认为更适合限制不会导致 IndexOutOfBoundsException 的响应长度的任何其他方式

见子串方法here

公共字符串子字符串(int beginIndex, int endIndex)

返回一个新字符串,它是该字符串的子字符串。子串 从指定的 beginIndex 开始并延伸到字符 index endIndex - 1。因此子字符串的长度是 endIndex-beginIndex.

例子:

 "hamburger".substring(4, 8) returns "urge"
 "smiles".substring(1, 5) returns "mile"

参数: beginIndex - 起始索引,包括在内。 endIndex - 结束索引,独占。回报: 指定的子字符串。 抛出: IndexOutOfBoundsException - 如果 beginIndex 为负数,或者 endIndex 大于此 String 对象的长度,或者 beginIndex 大于 endIndex。

【讨论】:

是的,这解决了 Volley 问题。我从developer.android.com 上的文档中以 1:1 的比例拿了这个例子,我没想到它在这种简单的情况下可能不起作用。【参考方案3】:

我不是 Lua 专家,但我认为您在发送响应之后 注册了“发送”回调。

我认为你应该把它移到连接函数中:

station_cfg=
station_cfg.ssid="Dom"
station_cfg.pwd="lalala"
wifi.sta.config(station_cfg)
function receive(conn, request)
        print(request)
        print()
        local buf = "";
        buf = buf.."<!doctype html><html>";
        buf = buf.."<h1> ESP8266 Web Server</h1>";
        buf = buf.."</html>";
        conn:send(buf);  
        collectgarbage();

end

function connection(conn) 
    conn:on("receive", receive) 
    conn:on("sent", function(sck) sck:close() end);   
end

srv=net.createServer(net.TCP, 30) 
srv:listen(80, connection)

【讨论】:

感谢您的帮助,但并没有解决问题。现在我看到打印在 esp(服务器反应)上的请求,但我无法使用浏览器加载页面。 当然我无法在 Android 应用程序中打印响应。

以上是关于Android & NodeMCU,从服务器接收响应不能正常工作?的主要内容,如果未能解决你的问题,请参考以下文章

NodeMCU烧录microPython固件

NodeMCU入门:搭建Web服务器,配置网络连接

NodeMCU-ESP8266连接阿里云Iot平台进行数据监测

无法从 NodeMCU 板连接到 Wi-Fi 网络

如何从 Lua NodeMCU 中的日期和时间字符串创建日期对象?

NodeMCU 闪烁错误