原理

1.首先理解什么是YModem通讯?

YModem协议是XModem的改进协议,它最用于调制解调器之间的文件传输的协议,具有快速,稳定传输的优点。它的传输速度比XModem快,这是由于它可以一次传输1024字节的信息块,同时它还支持传输多个文件,也就是常说的批文件传输。

YModem分成YModem-1K与YModem-g。

我使用的是YModem-1K 也就是一次传输1024字节。

YModem-1K用1024字节信息块传输取代标准的128字节传输,数据的发送回使用CRC校验,保证数据传输的正确性。它每传输一个信息块数据时,就会等待接收端回应ACK信号,接收到回应后,才会继续传输下一个信息块,保证数据已经全部接收。

YModem-g传输形式与YModem-1K差不多,但是它去掉了数据的CRC校验码,同时在发送完一个数据块信息后,它不会等待接收端的ACK信号,而直接传输下一个数据块。正是它没有涉及错误校验,才使得它的传输速度比YModem-1K来得块。

一般都会选择YModem-1K传输,平时所说的YModem也是指的是YModem-1K。下面就讲讲它的传输协议

由于上面都是些 C语言相关的所以省略了直接进入主题。 2.理解传输数据格式

/**
 * ========================================================================================
 * THE YMODEM:
 * Send 0x05>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>* 发送0x05
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
 * SOH 00 FF "foo.c" "1064'' NUL[118] CRC CRC >>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
 * STX 01 FE data[256] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 * ACK STX 02 FD data[256] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 * ACK STX 03 FC data[256] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * STX 04 FB data[256] CRC CRC>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * SOH 05 FA data[100] 1A[28] CRC CRC>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * EOT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< NAK
 * EOT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< C
 * SOH 00 FF NUL[128] CRC CRC >>>>>>>>>>>>>>>>>>>>>>>
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ACK
 * ===========================================================================================
 **/

我们用的设备首先要发送0x05与蓝牙通讯 然后设备返回一个C 接受到C后立即发送头部包到设备 此处 需要CRC16校验 采用标准的欧美标准

接下来就可以依次进行数据发送

注意:每一个公司的协议是不一样的但是你理解原理之后 协议不管怎么改 都可以去解决。

发送YModem到蓝牙的关键代码 根据底层的协议去进行发送数据

//接受终端数据然后再发送数据到终端
- (void)setOTADataWithOrderStatus:(NSString *)status fileName:(NSString *)filename {
    //发送头包
    if([status isEqual:OTAC]){
        NSLog(@"Head");
        NSData *data_first = [self prepareFirstPacketWithFileName:filename];
        if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
            [self.delegate onWriteBleData:data_first];
        }
    }
    //发送第一包 和 最后的结束包 ACK/C
    else if([status isEqual:OTASTART]){
        if(index_packet>0){
            NSData *data = [self prepareEndPacket];
            if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
                [self.delegate onWriteBleData:data];
            }
            index_packet = OTAUPEND;
        }else{
            // 正式包数组 获取所有拆解包放入数组中存储
            if (self.packetArray.count==0) {
                self.packetArray = [self preparePacketWithFileName:filename];
            }
            NSData *data = self.packetArray[index_packet];
            
            //写入蓝牙数据
            if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
                [self.delegate onWriteBleData:data];
            }
            index_packet_cache = index_packet;
        }
    }
    
    //接受到ACK
    else if([status isEqual:OTAACK]){
        if(index_packet==OTAUPEND){
            NSLog(@"升级完成");
        }
        index_packet++;
        NSLog(@"ACK");
        if (index_packet < self.packetArray.count) {
            if (index_packet != index_packet_cache) {
                self.packetArray = [self preparePacketWithFileName:filename];
                NSData *data = self.packetArray[index_packet];
                //拆包发送
                if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
                    [self.delegate onWriteBleData:data];
                }
            }
            index_packet_cache = index_packet;
        }else{
            Byte byte4[] = {0x04};
            NSData *data23 = [NSData dataWithBytes:byte4 length:sizeof(byte4)];
            NSLog(@"准备结束第一次OTA");
            if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
                [self.delegate onWriteBleData:data23];
            }
        }
        //沉睡300ms
        [NSThread sleepForTimeInterval:0.5];
    }
    //接受到NAK的时候
    else if([status isEqual:OTANAK]){
        if(index_packet>0){
            Byte byte4[] = {0x04};
            NSData *data23 = [NSData dataWithBytes:byte4 length:sizeof(byte4)];
            NSLog(@"准备结束第二次OTA");
            if([self.delegate respondsToSelector:@selector(onWriteBleData:)]){
                [self.delegate onWriteBleData:data23];
            }
        }else{
            NSLog(@"升级失败了");
        }
    }
    
    //通过代理返回当前你的升级大小
    if(self.packetArray.count>0){
        if([self.delegate respondsToSelector:@selector(onCurrent:onTotal:)]){
            [self.delegate onCurrent:index_packet onTotal:self.packetArray.count];
        }
    }
}

具体的详细过程 请看YYModemOCDemo

https://github.com/ArdWang/YModemlib_iOS

如果你喜欢就给我个star吧 目前更新到 v2.0.0版本

https://github.com/ArdWang/YModemOCDemo