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

之所以我们能够通过无线连接EV3,根本原因在于EV3的源码内建了一套无线连接通信的机制。
这套机制是这种:
1)EV3在连接到无线网络后,就不断地从3015port发送UDP数据。数据的格式例如以下:
Serial-Number: 0016533f0c1e
Port: 5555
Name: EV3
Protocol: EV3

从这个UDP数据中,我们能够获取其ip地址,设备序列号两个关键数据。

2)拥有了ip地址,我们就能够建立TCP连接连接到EV3,port为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那边接收的不论什么数据包括port数据这是在这里进行处理。

- (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返回port数据而且发送notification让界面更新。仅仅要接收到了信息。那么我们就已经成功连接而且能够控制EV3了。

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

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

在下一篇文章中,我们讲介绍怎样给EV3发送命令,怎样创建命令。

敬请期待!

【本文为原创文章,版权全部,转载请注明出处,谢谢。songrotek@qq.com

版权声明:本文博主原创文章,博客,未经同意不得转载。

【iOS与EV3混合机器人编程一系列五个】iOS_WiFi_EV3_Library 解剖连接EV3的更多相关文章

  1. 【iOS与EV3混合机器人编程系列之四】iOS_WiFi_EV3_Library 剖析之中的一个:WiFi UDP和TCP

    在上一篇文章中.我们通过编写EV3 Port Viewer项目实现了iOS监測EV3的实时端口数据. 程序最核心的部分就是我们的开源码库iOS_WiFi_EV3_Library. 那么,在本文中,我们 ...

  2. 【iOS与EV3混合机器人编程系列之三】编写EV3 Port Viewer 应用监測EV3port数据

    在前两篇文章中,我们对iOS与EV3混合机器人编程做了一个主要的设想.而且介绍了要完毕项目所需的软硬件准备和知识准备. 那么在今天这一篇文章中,我们将直接真正開始项目实践. ==第一个项目: EV3 ...

  3. 【iOS与EV3混合机器人编程系列之中的一个】iOS要干嘛?EV3能够更酷!

    乐高Mindstorm EV3智能机器人(下面简称EV3)自从在2013年的CES(Consumer Electronics Show美国消费电子展)上展出之后,就吸引了全球广大机器人爱好者的眼球!E ...

  4. Ubuntu 14 安装 “宋体,微软雅黑,WPS Office的symbol、wingdings、wingdings 2、wingdings 3、webding字体,Consolas雅黑混合版编程字体” 等 Windows 7 下的字体

    Windows平台下,“宋体”.“微软雅黑”.“Courier New(编程字体)”用的比较多,看的也习惯了.那如何在 Ubuntu下也安装这些字体呢? 操作步骤如下: 第一步:从 Windows 7 ...

  5. 混合语言编程:启用CLR(公共语言运行时编译)让C#调用C++

    前言 关于混合C#和C++的编程方式,本人之前写过一篇博客(参见混合语言编程:C#使用原生的Directx和OpenGL),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct ...

  6. iOS UI高级之网络编程(HTTP协议)

    HTTP协议的概念 HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响 ...

  7. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

  8. [Java并发编程(五)] Java volatile 的实现原理

    [Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...

  9. Learning ROS for Robotics Programming - Second Edition(《ROS机器人编程学习-第二版》)

    Learning ROS for Robotics Programming - Second Edition <ROS机器人编程学习-第二版> ----Your one-stop guid ...

随机推荐

  1. jQuery选择器部分知识点总结

    一.jQuery选择器的优势 1.使用CSS选择器时,开发人员需要考虑主流浏览器是否支持某些选择器,而在jQuery中,开发人员则可以放心的使用jQuery选择器而无需考虑浏览器是否支持这些选择器. ...

  2. Java面试——基础

    1,作用域,Java只有public,protect,private,默认是default相当于friendly 作用域 当前类          同一package 子类            其它 ...

  3. 解决spring mvc 上传报错,Field [] isn't an enum value,Failed to convert value of type 'java.lang.String[]' to required type '

    没有选择附件,但是点击上传按钮的时候会报错. 之前不选择文件,直接上传空文件是可以的,后来不知道改了什么就不行了. 错误信息: -- :: [http--] TRACE org.springframe ...

  4. C语言笔记(枚举)

    关于枚举,在我以前写程序的时候,几乎是没有使用过的,只是偶尔会在一下别人写的驱动库中有看到过.今天看了朱老师的视频,准备将枚举相关的东西总结一下. 一.关于枚举,你需要知道 (1)在C语言中就是一些符 ...

  5. 学c语言做练习之文件

    打开两个文件,让程序打印第一个文件的第一行,第二个文件的第一行,第一个文件的第二行,第二个文件的第二行,依此类推,直到打印完行数较多的文件的最后一行. #include<stdio.h> ...

  6. UML类图标识

    矩形框:类 第一层:类名(抽象类用斜体). 第二层:属性(‘+’ 表示 public.‘-’ 表示 private.‘#’ 表示 protected). 第三层:方法. <<interfa ...

  7. codevs 2806 红与黑

    2806 红与黑  时间限制: 1 s  空间限制: 64000 KB  题目等级 : 白银 Silver 题解  查看运行结果     题目描述 Description 有一个矩形房间,覆盖正方形瓷 ...

  8. java 双重检查模式

    java 双重检查模式 在并发环境下 兼顾安全和效率 成例(Idiom)是一种代码层次上的模式,是在比设计模式的层次更具体的层次上的代码技巧.成例往往与编程语言密切相关.双重检查成例(Double C ...

  9. [Delphi]检查URL是否有效的函数

    function CheckUrl(url: string): boolean; var hSession, hfile, hRequest: hInternet; dwindex, dwcodele ...

  10. VS2010中水晶报表应用及实例

    原文:VS2010中水晶报表应用及实例 基本分类如下:第一部分:VS2010简介VS2010是微软的提供的一套完整的开发环境,功能也是相当的大微软宣布了下一代开发工具和平台的正式名称,分别称为“Vis ...