ExternalAccessory串口通信

ExternalAccessory 使用文档

项目下载地址

  • 前言

    公司希望通过串口通信的方式实现苹果手机与公司产品进行通信,通过Lighting接口,也就是苹果的数据线。苹果的API ExternalAccessory就是来解决这个问题的。

👇以下介绍一下ExternalAccessory的用法

简介

ExternalAccessory通过三个类来实现通信

  1. EAAccessory 代表外部设备,包含了外部设备的信息;
  2. EAAccessoryManager 外部设备的管理者;
  3. EASession 当与一个外部设备建立通信渠道后,整个会话由这个类操作;
为项目添加ExternalAccessory通信机制的步骤
1. 引入类库
  引入framework ExternalAccessory.framework
  在使用时添加 #import <ExternalAccessory/ExternalAccessory.h>
2. 在plist 文件中加入 UISupportedExternalAccessoryProtocols 字段,这是一个数组,将所有用到的协议字符串加入到这个数组中。这里的协议字符串是外设提前预制的,需要与硬件开发人员确认。苹果系统已经帮我们管理了已经连接的设备,这里添加协议名称的目的是告诉系统我的APP可以与包含这个协议的外设进行交互。
  <key>UISupportedExternalAccessoryProtocols</key>
	<array>
		<string></string>
	</array>
3. 获取已经与手机连接的全部外部设备,监听设备的链接以及断开的状态变化。
     _accessoryList = [[NSMutableArray alloc] initWithArray:[[EAAccessoryManager sharedAccessoryManager] connectedAccessories]];//这个数组中包含的是 EAAccessory
     
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessoryDidConnect:) name:EAAccessoryDidConnectNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessoryDidDisconnect:) name:EAAccessoryDidDisconnectNotification object:nil];
    //调用这个方法告诉系统,当设备链接状态发生改变时给APP发送通知。
    [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
4. 根据protocolString 筛选出EAAccessory 创建会话 EASession ,并且监听收到信息以及可以发送信息的回调。
- (EASession *)openSessionForProtocol:(NSString *)protocolString
{
    NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager]
                            connectedAccessories];
    EASession *session = nil;
    
    for (EAAccessory *obj in accessories)
    {
        if ([[obj protocolStrings] containsObject:protocolString])
        {
            _accessory = obj;
            _accessory.delegate = self;
            break;
        }
    }
    
    if (_accessory)
    {
        session = [[EASession alloc] initWithAccessory:_accessory
                                           forProtocol:protocolString];
        if (session)
        {
            [[session inputStream] setDelegate:self];
            [[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                             forMode:NSDefaultRunLoopMode];
            [[session inputStream] open];
            [[session outputStream] setDelegate:self];
            [[session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                              forMode:NSDefaultRunLoopMode];
            [[session outputStream] open];
        }
    }
    
    return session;
}

#pragma mark - NSStream Delegate

- (void)stream:(NSStream*)theStream handleEvent:(NSStreamEvent)streamEvent
{
    switch (streamEvent)
    {
        case NSStreamEventHasBytesAvailable:
        {// Process the incoming stream data.
            [self receiveData];
        }
            break;
            
        case NSStreamEventHasSpaceAvailable:
        {// Send the next queued command.
            [self writeData];
        }
            break;
            
        default:
            break;
    }
    
}
  
5. 接收配套设备的信息,以及向配套设备发送信息。
接收数据:
-(void)receiveData
{
    NSInteger maxLength = 128;
    uint8_t readBuffer [maxLength];
    //是否已经到结尾标识
    BOOL endOfStreamReached = NO;
    // NOTE: this tight loop will block until stream ends
    while (! endOfStreamReached)
    {
        NSInteger bytesRead = [_session.inputStream read: readBuffer maxLength:maxLength];
        if (bytesRead == 0)
        {//文件读取到最后
            endOfStreamReached = YES;
        }
        else if (bytesRead == -1)
        {//文件读取错误
            endOfStreamReached = YES;
        }
        else
        {
            NSString *readBufferString =[[NSString alloc] initWithBytesNoCopy:readBuffer length:bytesRead encoding: NSUTF8StringEncoding freeWhenDone: NO];
            NSLog(@"收到设备信息:%@",readBufferString);
            TTSLOG(@"收到设备信息");
        }
    }
}


发送数据: 发送数据没有必要在状态回调后再发送,也可以通过判断hasSpaceAvailable的状态来决定是否能够发送。
-(void)writeData
{
    BOOL isAvailable = _session.outputStream.hasSpaceAvailable;
    if (isAvailable == YES) {
        NSData *data = [[NSData alloc]initWithBase64EncodedString:@"出发了老铁" options:NSDataBase64DecodingIgnoreUnknownCharacters];
        [_session.outputStream write:[data bytes] maxLength:data.length];
    }
    
}

posted @ 2018-04-12 10:54  慢慢儿  阅读(1977)  评论(2编辑  收藏  举报