固定式扫描,串口通讯,tcp通讯

第一次接触固定式扫描的项目,项目背景:在流水线的某处安装一个固定式扫描的设备及程序,如扫描到条码,且程序能通过该条码的检验,即流水线正常流水。否则(没有扫描到或者程序不通过该条码的检验)将做停线处理,此处对接plc设备。处理完后用扫描枪补扫该条码,并恢复流水线。

 设备:安卓工业平板,扫描器和扫描器配套的控制盒,plc控制盒(简化plc的控制程序,如停线发送一个ng指令即可),各种串口线、接线等。

2021-08,使用两个串口通信的方式开发,一个串口用于接收固定式扫描器扫到的数据,另一个串口用于对接plc控制盒发送停线及复位的指令。

遇到的问题:无法同时使用两个串口通讯,所以用到了一个不治本的方法,每次使用到另一个串口的时候,先提前重连该串口。比如在需要发送停线的指令之前先重新连接plc的串口,发送复位指令后就重新连接固定扫描的串口。但是该方式不能治本,偶尔会出现程序闪退的情况等等。也有一些程序逻辑问题,但是在代码上根本看不到有任何逻辑问题。使用了两三个月后,出现了设备刚开机,扫描枪补扫扫不进去的情况,页面也卡死不动。观察了几天,再代码上找不到原因,后续更换了工业平板才不会出现扫不进去卡死的情况。

2021-11,前面两三个月出现的各种各样的问题,迫使我更换通讯方式,固定式扫描的原串口方式改为tcp通讯。记录一下tcp的代码。

package com.maiot.tcp;

import java.net.*;
import java.io.*;
import java.util.Date;
/**
 * 如果app端连接了多个,socket总是以最新的新建的
 * @params
 * @remarks 客户端接收数据,设置回调是为了给前台html重写得到监听的数据做处理
 * @return
 * @author yxf
 * @date 2021-11-02 11:27
 */
public class Client {
    public Socket socket = null;
    public OutputStream os = null;
    public InputStream is = null;

    public SocketThread socketThread = new SocketThread();
    String heartbeat = "ping";//心跳
    public static void main(String[] args) {
        Client client = new Client();
        client.setTcpCallback(new TcpCallback() {
            @Override
            public void onReceiveData(String data) {
                System.out.println(new Date()+data);
            }

            @Override
            public void msg(String msg) {

            }
        });
        client.new SocketThread().start();
    }
    /**
     * 数据回调
     */
    public TcpCallback tcpCallback;
    public void setTcpCallback(TcpCallback tcpCallback){
        this.tcpCallback = tcpCallback;
    }

    public boolean is_true=true;
//    ip,端口
    public String host="192.168.12.201";
    public int port=51235;
    public void setHost(String host){this.host=host;}
    public void setPort(int port){this.port=port;}
    public int out_time=3;//超过多少秒没有收到服务端数据,就重连,       固扫的心跳包1-2秒

    public int timeout=3000;//连接服务器的超时时间,毫秒
    public void setTimeout(int timeout){this.timeout=timeout;}
    /**
     * 发送心跳包
     */
    public void sendHeartbeat() {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            Thread.sleep(10 * 1000);// 10s发送一次心跳
                            os.write(heartbeat.getBytes());//经测试,这里端口不对就会报错空指针异常
                            os.flush();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void socket_close() {
        if(socket!=null) {
            try {
                is_true=false;//不执行了,避免一直重连,新建
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public class SocketThread extends Thread {

        @Override
        public void run() {
            long startTime = System.currentTimeMillis();
//            sendHeartbeat();
            while (is_true) {
                try {
                    if (socket == null || socket.isClosed()) {//如未开启,就执行连接
                        socket = new Socket();
                        SocketAddress endpoint = new InetSocketAddress(host, port);// 连接socket
                        try {
                            socket.connect(endpoint, timeout);//设定一个超时时间,如果在该时间端未连接,就抛出异常
                        } catch (SocketTimeoutException e) {
                            e.printStackTrace();
                            tcpCallback.msg("连接超时,请确认该IP是否开启");//执行回调函数
                            break;
                        }
                        os = socket.getOutputStream();
                    }
                    Thread.sleep(100);
                    try {
                        is = socket.getInputStream();//
                    } catch (SocketException e) {//Socket is not connected 不是连接状态
                        e.printStackTrace();
                        tcpCallback.msg("未连接成功,请检查IP和端口是否正确");//执行回调函数
                        break;
                    }

                    int size = is.available();
                    if (size <= 0) {
//                        System.out.println(socket+"时间差"+(System.currentTimeMillis()-startTime));
                        if ((System.currentTimeMillis() - startTime) > out_time * 1000) { // 如果超过多少秒没有收到服务器发回来的信息,说明socket连接可能已经被远程服务器关闭
                            System.out.println(socket+"开始重连了");
                            socket.close(); // 这时候可以关闭socket连接,前面会检测到并重新连接
                            startTime = System.currentTimeMillis();
                        }
                        continue;
                    } else {
                        startTime = System.currentTimeMillis();
                    }
                    byte[] resp = new byte[size];
                    is.read(resp);
                    String response = new String(resp, "GB2312");//以防乱码
                    System.out.println(socket+response);
//                    System.out.println(response.length());//心跳长度是7
//                    有粘包情况,粘包条码和心跳一起了 如6705331421115413#189\r\n
                    if(!response.contains("#189")){
                        tcpCallback.onReceiveData(response);//执行回调函数
                    }else {
                        if(response.length()>7){//粘包条码和心跳一起了 如6705331421115413#189,长度是16+7,,,也有心跳加NG的情况,长度是2+7
                            System.out.println("粘包了,长度:"+response.length());
                            tcpCallback.onReceiveData("NG");//模拟发送ng
                        }
                    }
                }
                catch (ConnectException e){//捕获服务器ip可能不开通监听状态的异常,不捕获会闪退
                    e.printStackTrace();
                    tcpCallback.msg("请选择正确的固扫IP和端口");//执行回调函数
                    break;
                }
                catch (NoRouteToHostException e){//捕获没有该主机ip存在的异常,不捕获会闪退
                    e.printStackTrace();
                    tcpCallback.msg("局域网内没有该IP:"+host);//执行回调函数
                    break;
                }
                catch (Exception e) {
                    e.printStackTrace();
                    try {
                        if(socket!=null&&is!=null&&os!=null){
                            socket.close();
                            is.close();
                            os.close();
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }
    }

}
package com.maiot.tcp;
/**
 *
 * @params
 * @remarks 设置回调函数
 * @return
 * @author yxf
 * @date 2021-11-02 11:27
 */
public interface TcpCallback {
//    收到的数据
    void onReceiveData(String data);

    //    返回异常提示
    void msg(String msg);
}

工业平板端的程序作为tcp客户端,贴出其主要代码。

package com.maiot.tcp;

import java.io.IOException;
import java.util.Date;
/**
 *
 * @params
 * @remarks 客户端接收数据,启动线程
 * @return
 * @author yxf
 * @date 2021-11-02 11:27
 */
public class Tcp_conn {
    public static void main(String[] args) {
        Client client = new Client();
        client.setTcpCallback(new TcpCallback() {
            @Override
            public void onReceiveData(String data) {
                System.out.println(new Date()+data);
            }

            @Override
            public void msg(String msg) {

            }
        });
        conn(client);
    }
//    开启线程
    public static void conn(Client client){
//        client.new SocketThread().start();
        client.socketThread.start();
    }
//    通知线程,该中断了
    public static void close(Client client) throws IOException {
//        client.new SocketThread().start();
        if(client.socket!=null){
            client.socket.close();
        }
        if(client!=null){
            client.socket_close();
        }
//        if(client.is!=null){
//            client.is.close();
//        }
//        if(client.os!=null){
//            client.os.close();
//        }
        client.socketThread.interrupt();
    }
}

到现场调设备的时候。跟现场内部人员协调要把平板和固定式扫描器的ip固定。

哎呀,先不写了。

版权声明:本文为CSDN博主「葫芦啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_37769260/article/details/121331825

生成海报
点赞 0

葫芦啊

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32+W5500网络通信

一、Modbus/TCP协议 1.查询报文 00 6D 00 00 00 06 01 03 00 00 00 01 00 6D 查询编号 00 00 协议 00 06 数据包长度 01 设备编号 03 功能码 00 00 起始地址 00 01

芯片设计IP核公司总结与分析

下图是IPnest公司在2020年4月发布的关于2018年和2019年全球 最大的10家芯片设计IP核公司名单。 芯片设计难度挺大但也不是很多人想象的从0开始的那种难,绝大部分芯片设计公司都是买IP核然后整合一下,最

STM32F103基于W5500实现Modbus简单TCP通信

一,目的 掌握W5500网络模块的特点,参考模块厂商配套资料,完成TCP数据通信、DHCP自动获取IP的程序设计。在此基础上,实现应用层modbus、httpd(web服务