【徕卡全站仪Geocom开发】开发日志#03

    上周去了趟广州出差,没及时更新,周一上班摸鱼写写最近的开发经历

1 技术路线研究

    我联系了徕卡官方的技术支持,对方表示徕卡是可以通过串口服务器链接互联网的,在确定路线可用之后我开始慢慢去了解这个过程(这里贴一张串口服务器的工作原理,不知道如何去图片水印,有人知道麻烦私信告诉我一下)
在这里插入图片描述

    大概的路线想明白了,设备价格也还算可以接受,我总共买了两个设备,一个是将RS232转以太网设备,一个是无线上网设备。无线上网的设备比较好理解,插上就可以上网,无非就是账号注册的时候稍微麻烦一点。
    串口设备的说明文档走马观花地过了一遍,大致了解串口服务器总共有五种工作模式:TCP服务器、TCP客户端、UDP服务器、UDP客户端、HTTP客户端。因为之前主要的工作全部集中在uni-app这里,理所当然地将HTTP作为主要的研究方向。但是这里和我的需求不相符,我需要的是传送给徕卡设备指令,然后徕卡设备才会发送指令回执,而这个HTTP客户端显然不满足我的需求,想要实现数据的双向传输得用TCP。
    然后我尝试使用webSocket去尝试连接TCPServer工作模式下的串口服务器,但是仍然以失败告终。难道又要去翻Native.js?安卓原生开发里面是存在有TCP链接的,无奈只能先去尝试使用安卓原生的功能。但是很快又遇到一个新的问题:串口服务器连接的无线上网设备的ip是根据运营商来确定的,也就是说服务器的ip不固定。
    后来一次很偶然的机会,因为这个项目涉及到坐标矩阵的变换,我在解方程的时候看到之前绘制的项目构思,设备直接链接的并不是手机客户端,而是经过了一个服务器,通过服务器来连接所有的其他传感器设备和客户端。那我为什么不使用串口服务器的TCPClient工作模式连接另外一个服务器呢?大致的思路如下所示:
在这里插入图片描述    这个服务器同时监听TCP和HTTP请求,这样手机端就不用考虑这么多问题了,只需要正常使用HTTP请求就可以,具体的TCP相关内容丢给后端工程师,我就不用管了,哈哈哈。

2 内容实现

    额,高兴的太早了,这个项目只有我一个人,最后还是我自己在处理这个问题,那开始吧,写一个监听TCP和HTTP的服务器。先用Node.js写一个简单的:

var net = require('net');
var http = require('http');
var crypto = require('crypto');

var socketList = [];

var httpServer = http.createServer((request, response) => {
    let post = '';
    response.on('error', (err) => {
        console.log(err);
    })
    request.on('data', chunk => {
        post += chunk;
    })
    request.on('end', () => {
        //接收到消息
        var data = JSON.parse(post);
        var socketItem = socketList.find(item => item.name == data.name);
        //没有找到指定的TCP链接,返回错误
        response.writeHead(200, { 'Content-Type': 'text/json' });
        if (!socketItem) {
            response.end(JSON.stringify({ result: "TCPNotFound", success: false }));
        }
        else {
            var command = `%R1Q,${data.command}\r\n`;
            console.log(`来自http请求发送的命令:${data.command}`);
            socketItem.socket.write(command)
            socketItem.socket.once('data', (data) => {
                var dataStr = data.toString();
                console.log(`命令响应为:${dataStr}`);
                var result = dataStr.match(/(?<=%R1P,0,0:).+?(?=,|\n|\r)/g);
                if (!result) {
                    response.end(JSON.stringify({ result: 'CommandError', success: false, originData: dataStr }));
                }
                else if (result[0] != '0') {
                    response.end(JSON.stringify({ result: 'ParamsError', success: false, originData: dataStr }));
                }
                else {
                    response.end(JSON.stringify({ result: 'Success', success: true, originData: dataStr }));
                }
            })
        }
    })
}).listen(18000);

var tcpServer01 = net.createServer(function (socket) {
    let uuid = crypto.randomUUID();
    socket.once('data', (data) => {
        if (data.includes('leicaConnect')) {
            socketList.push({ uuid, name: data.split('|')[1], socket })
            console.log(`新的设备连接:\n名称:${data.split('|')},uuid:${uuid}\n`);
        }
    })
    socket.once('close', () => {
        let findIndex = socketList.findIndex(item => item.uuid == uuid);
        if (findIndex > -1) {
            socketList.splice(findIndex, 1);
            console.log(`设备连接断开:\n名称:${data.split('|')},uuid:${uuid}\n`);
        }
    })
}).listen(18001);

console.log('服务器启动成功')

    单位内网对ip做了路由处理,无法直接看到自己的外网ip,这个简单,用个内网穿透到指定的外网ip就可以了(主要是目前在测试,服务器上我们的华为云服务器需要写流程很麻烦,我就这样应急了)串口服务器的TCPClient工作模式原理是每隔指定的时间向指定的ip和端口发送连接请求,直到连接成功。同时还可以设置注册包和心跳包,前者是在连接成功之后发送的身份验证一样的东西,后者是每隔一段时间发送一个数据包,确认连接是否完好。
    我在这里写了一个简单的注册包,后面可以考虑使用aes加密来处理身份验证的问题。最后将写好的蓝牙模块这里的链接模式替换为HTTP请求就可以了。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值