【iOS与EV3混合机器人编程系列之五】iOS_WiFi_EV3_Library 剖析之连接EV3

2024-01-21 19:58

本文主要是介绍【iOS与EV3混合机器人编程系列之五】iOS_WiFi_EV3_Library 剖析之连接EV3,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上一篇文章中,我们讲解了如何用开源代码库CocoaAsyncSocket来实现iOS上的UDP和TCP数据通信。那么在本文中,我们将介绍在CocoaAsyncSocket的基础如何使用UDP和TCP连接EV3的机制。

之所以我们能够通过无线连接EV3,根本原因在于EV3的源代码内建了一套无线连接通信的机制。
这套机制是这样的:
1)EV3在连接到无线网络后,就不断地从3015端口发送UDP数据,数据的格式如下:
Serial-Number: 0016533f0c1e
Port: 5555
Name: EV3
Protocol: EV3
从这个UDP数据中,我们可以获取其ip地址,设备序列号两个重要数据。
2)拥有了ip地址,我们就可以建立TCP连接连接到EV3,端口为5555
3)在连接上TCP后,我们就可以向EV3发送数据了,我们必须先发送一个解锁信息获取控制EV3的权限才能实现对EV3的有效控制,解锁信息格式为:
GET /target?sn=SERIAL_NUMBER VMTP1.0 Protocol: EV3
sn=对应设备的序列号,就是我们从UDP信息中获取的序列号
4)解锁信息发送成功后,EV3会返回一条信息:”Accept:EV340”。如果我们收到了这条信息,就意味着我们已经解锁成功,现在我们就可以发送特定的EV3命令来控制EV3了!!

连接EV3的奥秘就是上面这么几句话了。恭喜你,你已经知道Secret了!那么现在我们要通过具体的程序来实现它。

在代码库中我们建立了一个类EV3WifiManager来管理EV3的连接和数据传输功能,并建立了EV3WifiBrowserViewController的视图控制器来作为EV3连接管理的界面。

为了更好地存储管理EV3设备数据,我们还建立了EV3Device来存储EV3的信息。

关于界面的设计本文就不谈了,仅谈谈实现连接的核心代码。

== Step 1:连接UDP并接收数据 ==
连接方法我们在上一篇文章已经讲了,本文不再谈。
现在主要说明一下数据处理部分:
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
      fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
        // 1
        NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if (msg)
        {
        // 2
        NSString *serialNumber = [msg substringWithRange:NSMakeRange(14, 12)];
        
        NSString *host = [GCDAsyncUdpSocket hostFromAddress:address];
        
        EV3Device *device = [self.devices objectForKey:host];

        if (!device && host.length < 20) {
            
// 3
            EV3Device *aDevice = [[EV3Device alloc] initWithSerialNumber:serialNumber address:host tag:self.devices.count isConnected:NO];
            
            
            
            // 4
            dispatch_queue_t tcpSocketQueue = dispatch_queue_create("com.manmanlai.tcpSocketQueue", DISPATCH_QUEUE_CONCURRENT);
            GCDAsyncSocket *tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:tcpSocketQueue];
            
            aDevice.tcpSocket = tcpSocket;
            
            
            [self.devices setObject:aDevice forKey:aDevice.address];
            
            
            
            if ([self.delegate respondsToSelector:@selector(updateView)]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.delegate updateView];
                });
            }
        }
        
        }
        else
        {
        NSLog(@"Error converting received data into UTF-8 String");
        }
        // 5
        [self.udpSocket sendData:data toAddress:address withTimeout:-1 tag:0];
}

1、将获取的转化为字符串
2、通过截取字符串来获取EV3设备的序列号,并通过hostFromAddress:获取特定连接的名称(每一个连接都有一个host名称)作为EV3设备的key来存储EV3的信息。
3、新建一个EV3Device实例来存储设备信息
4、新建一个TCP socket用于连接EV3。
5、将原UDP数据返回给EV3。(这一步省略也没有关系)

== 连接TCP并解锁 ==
TCP的连接这里不讲,不清楚的童鞋还请看上一篇文章。
在实现中,我们在界面上显示了ip地址,点击后开始连接。
一旦连接成功,我们就立即发送解锁数据,并立即接收数据。代码如下:

- (void)connectTCPSocketWithDevice:(EV3Device *)device
{
    
    GCDAsyncSocket *tcpSocket = device.tcpSocket;
    // connnect
    NSError *error = nil;
    if (![tcpSocket connectToHost:device.address
                                onPort:5555
                                 error:&error])
    {
        NSLog(@"Error connecting: %@", error);
        
    } else {
        NSLog(@"Connected");
        // write data
        NSLog(@"writing...");
        NSString *unlockMsg = [NSString stringWithFormat:@"GET /target?sn=%@ VMTP1.0 Protocol: EV3",device.serialNumber];
        NSData *unlockData = [unlockMsg dataUsingEncoding:NSUTF8StringEncoding];
        [tcpSocket writeData:unlockData withTimeout:-1 tag:MESSAGE_UNLOCK];
        
        [tcpSocket readDataWithTimeout:-1 tag:MESSAGE_UNLOCK];
        
    }
    
    
}

读取到数据后,我们就着手进行数据处理,由于这个代码库要支持多机连接,因此我们在每个EV3Device中处理数据。这里大家要注意就是我们从EV3那边接收的任何数据包含端口数据这是在这里进行处理。

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *host = sock.connectedHost;
    EV3Device *device = [self.devices objectForKey:host];
    
    [device handleReceivedData:data withTag:tag];        
}

这里我们只看处理解锁数据的过程:
case MESSAGE_UNLOCK:
        {
            NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSString *response =[httpResponse substringToIndex:12];
            if ([response isEqualToString:@"Accept:EV340"]) {
                self.isConnected = YES;
                NSLog(@"ev3 connected");
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self scanPorts];
                    [[NSNotificationCenter defaultCenter] postNotificationName:EV3DeviceConnectedNotification object:self];
                });
            }
                break;
        }

需要注意的是我们发送的每一条数据都有特定的标签以便于区分。对于解锁数据的信息,其对应的标签是MESSAGE_UNLOCK。代码方面需要说明的不是很多,核心就是判断接收到的信息是不是Accept:EV340,其余的代码就是直接发送命令让EV3返回端口数据并且发送notification让界面更新。只要接收到了信息,那么我们就已经成功连接并且可以控制EV3了。

需要说明的是有一些情况局域网中无法发送TCP数据,导致虽然连接上了TCP,但无法发送解锁信息。一般我都是用Android手机做热点。iPhone热点连接问题确实值得大家一起好好研究!

OK,那么大家可以看到,连接EV3并不是一件非常困难的事。只要通过上面几步,我们就能做到。

在下一篇文章中,我们讲介绍如何给EV3发送命令,如何创建命令。敬请期待!

【本文为原创文章,版权所有,转载请注明出处,谢谢!songrotek@qq.com】


这篇关于【iOS与EV3混合机器人编程系列之五】iOS_WiFi_EV3_Library 剖析之连接EV3的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/630663

相关文章

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

全屋WiFi 7无死角! 华硕 RP-BE58无线信号放大器体验测评

《全屋WiFi7无死角!华硕RP-BE58无线信号放大器体验测评》家里网络总是有很多死角没有网,我决定入手一台支持Mesh组网的WiFi7路由系统以彻底解决网络覆盖问题,最终选择了一款功能非常... 自2023年WiFi 7技术标准(IEEE 802.11be)正式落地以来,这项第七代无线网络技术就以超高速

java连接opcua的常见问题及解决方法

《java连接opcua的常见问题及解决方法》本文将使用EclipseMilo作为示例库,演示如何在Java中使用匿名、用户名密码以及证书加密三种方式连接到OPCUA服务器,若需要使用其他SDK,原理... 目录一、前言二、准备工作三、匿名方式连接3.1 匿名方式简介3.2 示例代码四、用户名密码方式连接4

MySQL 表的内外连接案例详解

《MySQL表的内外连接案例详解》本文给大家介绍MySQL表的内外连接,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录表的内外连接(重点)内连接外连接表的内外连接(重点)内连接内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

宝塔安装的MySQL无法连接的情况及解决方案

《宝塔安装的MySQL无法连接的情况及解决方案》宝塔面板是一款流行的服务器管理工具,其中集成的MySQL数据库有时会出现连接问题,本文详细介绍两种最常见的MySQL连接错误:“1130-Hostisn... 目录一、错误 1130:Host ‘xxx.xxx.xxx.xxx’ is not allowed

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I