【问题标题】:Using Android TCP Client app to interface with sensor使用 Android TCP Client 应用程序与传感器交互
【发布时间】:2015-04-18 18:40:03
【问题描述】:

更新 #2:BLUF:我想我找到了问题,但我需要帮助找出如何解决它。该设备需要一个带有前缀和后缀 STX>command ETX> 的命令(我必须删除左括号,以便 stackoverflow 会显示它)。当我使用 Hercules(有效)通过 TCP 发送时,主机正确解释 STX> 和 ETX> 并且只显示“命令”,但是我编写了一个 java 客户端程序发送相同的信息,但它在主机上显示为“STX >commandETX>”。 java有什么不同?


原文:

过去几天我一直在解决这个问题,但我没有想法,所以我在这里。首先是一些可能相关或不相关的背景信息: 我有一个 SICK LMS151 LIDAR 传感器,我需要通过 Android 应用程序访问它。传感器设计为 TCP 服务器,因此您可以作为客户端连接并发送命令 STX>sRN LMDscandataETX>。这会提示传感器将一堆数据返回给客户端。在计算机上,我可以在 TCP 客户端模式下使用 Hercules 之类的程序,发送命令并立即接收数据而不会出现问题。然而,让 Android 应用程序做同样的事情是有问题的(我在下面附上了客户端代码)。
我在一个单独的 android 设备上编写了一个服务器应用程序,我的客户端应用程序已经能够连接到该设备并交换数据。我通过连接发送命令“STX>sRN LMDscandataETX>”,这正是它在服务器端的显示方式。当服务器应用程序发送数据时,我可以在我的客户端上看到它。但是,当我尝试使用客户端连接到传感器时,它会连接但不响应我的数据请求。任何要研究的问题的想法都会有所帮助,因为在这一点上我很新鲜。谢谢!

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class TcpClient extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        runTcpClient();
    }

private static final int TCP_SERVER_PORT = 2111;
private void runTcpClient() {
    try {
        Socket s = new Socket("192.168.0.105", TCP_SERVER_PORT);
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
Log.i("TcpClient", "Connected!");
        //send output msg
        String outMsg = "<STX>sRN LMDscandata<ETX>"; 
        out.write(outMsg);
        out.flush();
        Log.i("TcpClient", "sent: " + outMsg);
        //accept server response
        String inMsg = in.readLine() + System.getProperty("line.separator");
        Log.i("TcpClient", "received: " + inMsg);
        //close connection
        s.close();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } 
}
}   

更新:今天在这方面花了更多时间。从 Apache 添加了一个 BoundedInputStream,希望我可能什么也没看到,因为传感器在每次读取结束时没有发送 /n 字符。也从 BufferedReader 转换为 Scanner。没有运气。我现在相当确信这不是我的客户端读取的问题,而是它以某种方式发送命令与计算机不同,因此传感器无法理解它。

【问题讨论】:

  • 我将建议在命令端缺少换行符作为嫌疑人,但也许您已经检查过了。你能在某个地方(也许在路由器上?)设置一个数据包扫描器来查看所有进出传感器的流量吗?看起来该仪器正在通过 TCP 代理一些较旧的串行协议,因此它的网络实现也有可能是相当“简单”的东西,作为事后的想法被移植到早期的设计中(即,错误或挑剔的细节它应该不是)。你能通过 Android 设备上的 connectbot 之类的工具与它交谈吗?
  • 感谢您的回复!老实说,我不确定如何在路由器上设置数据包扫描器,但我认为传感器最初设计为串行设备是对的。我下载了 Connectbot,它似乎可以连接,但我不知道如何在应用程序中输入数据。相反,我下载了另一个名为 TCP Client 的应用程序。它连接并且我可以发送数据,但传感器也不会响应它。通过测试的一个观察结果可能有用:我编写的 tcp 服务器会立即响应我的 java tcp 程序,但会挂断直到与 Hercules 断开连接......很奇怪。

标签: java android sockets tcp tcpclient


【解决方案1】:

好的,我解决了这个问题,我认为它值得分享。使用wireshark 后,我发现有效的命令是用STX> 和ETX> 代替\u0002 和\u0003。这些是标准的 TCP 页眉和页脚。我手动进入我的代码进行替换,瞧!它奏效了。

【讨论】:

  • "这些是标准的 TCP 页眉和页脚" - 没有。
  • @Malt 您在没有提供任何细节的情况下进行了更正,所以我的假设是您没有来源。 \u 是表示 unicode 消息的代码,STX(例如 \x02)是用于发送打包数据的标准“开始令牌”分隔符:www-01.ibm.com/support/knowledgecenter/SSBLQQ_8.6.0/… TCP 对我来说是新的,所以如果您有更好的信息,请纠正我。我只是要求比“不”更多的细节。
  • STX 和 ETX 是有时用作分隔符的符号。它们与 TCP 几乎没有关系,除了 TCP 是基于流的协议这一事实,并且从基于流的协议中读取消息的方法之一是使用分隔符。分隔符可以是任何未出现在消息中的内容。例如,在 HTTP(基于 TCP)中,分隔符是换行符。另一方面,“标准 TCP 标头”是这些东西:en.wikipedia.org/wiki/…,与 STX 和 ETX 无关。
猜你喜欢
  • 1970-01-01
  • 2012-01-04
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 2020-12-12
相关资源
最近更新 更多