美文网首页iOS蓝牙设备
iOS中蓝牙与打印机连接使用

iOS中蓝牙与打印机连接使用

作者: 寻找最亮的光 | 来源:发表于2019-05-22 21:02 被阅读0次

    公司最近帮一家物流公司做一个员工使用的APP,需要用到蓝牙去连接设备打印运单信息,下面记录一些在对接蓝牙打印时候遇到的问题,也总结一下其他技术文章中的一些知识点供大家参考,网上也有别人做好的第三方BabyBluetooth,这个第三方也可以在我们找的几种设备上正常打印,同学们可以去看看这个怎么使用,有问题的地方希望大家提出来。

    一、关于蓝牙开发的一些重要的理论概念:

    1、服务(services):蓝牙外设对外广播的时候一定会有一个服务,有些时候也可以是有多个服务,服务下面包含一些特性,服务可以理解成一个模块的窗口;
    2、特征(characteristic):特征存在于服务下面的,一个服务下面可以有多个特征,特征可以理解成具体实现功能的窗口,一般的特性都会有value,也就是特征值,是特征和外界交互的最小单位;
    3、UUID:蓝牙上的唯一标示符,为了区分不同服务和特征,就用UUID来表示。

    二、蓝牙连接的主要步骤

     1、创建一个CBCentralManager实例来进行蓝牙管理;
    
     2、使用CBCentralManager对象搜索扫描外围设备;
    
     3、连接外围设备;
    
     4、获得外围设备的服务;
    
     5、获得服务的特征;
    
     6、从外围设备读取数据;
    
     7、给外围设备发送(写入)数据。
    

    三、蓝牙连接和数据读写的具体步骤

    1、导入苹果系统蓝牙框架<CoreBluetooth/CoreBluetooth.h>

    2、遵循两个蓝牙框架相关的协议<CBCentralManagerDelegate,CBPeripheralDelegate>

    3、新建两个实例属性,一个特征属性
    @property (nonatomic, strong) CBCentralManager *centralManager; //中心管理者
    @property (nonatomic, strong) CBPeripheral *peripheral; //连接到的外设
    @property (nonatomic, strong) CBCharacteristic *characteristic; //特征

    4、实例化CBCentralManager对象进行蓝牙管理
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()]; //创建实例进行蓝牙管理

    在实例化该对象之后,就会触发下面这个必须实现的代理方法,否则在实例化之后会闪退,在该方法里面也可以获取到蓝牙的状态,可以在此处提示用户去打开蓝牙

    - (void)centralManagerDidUpdateState:(CBCentralManager *)central{
        NSString * state = nil;
        switch ([central state])
        {
            case CBCentralManagerStateUnsupported:
                state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
                break;
            case CBCentralManagerStateUnauthorized:
                state = @"The app is not authorized to use Bluetooth Low Energy.";
                break;
            case CBCentralManagerStatePoweredOff:
                state = @"Bluetooth is currently powered off.";
                break;
            case CBCentralManagerStatePoweredOn:
                state = @"work";
                break;
            case CBCentralManagerStateUnknown:
            default:
                ;
        }
    }
    

    客户的需求里面有下次进入该界面自动连接设备的功能,开始做的时候是实例化之后马上开始连接之前的设备,但是总是连接不上。实际上等这个回调函数调用之后就可以连接了,包括去搜索也是一样,如果大家操作相关功能之后没有效果,可能是这个函数还没调用的原因,怎么连接之前的设备一会会讲到。

    5.扫描蓝牙设备(根据SERVICE_UUID来扫描外设,如果不设置则扫描所有蓝牙设备)

    [central scanForPeripheralsWithServices:nil options:nil];
    

    执行扫描动作之后,如果扫描到外设了,就会自动回调下面的协议方法

    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
         /*这边可以打印设备的名称,我们可以先将所有搜索到的设备都存储起来显示到UI上,根据选择来连接
          搜索到的设备会重复,所以需要过滤
          peripheral.name
         */
          if(![self.deviceLists containsObject: peripheral]){
              [self.deviceLists addObject: peripheral];
          }
    }
    

    6.连接外围设备

    选择设备进行连接
    [central connectPeripheral:peripheral options:nil];
    

    连接外围设备,中心管理者连接外设成功,如果连接成功就会回调这个协议方法

    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
        /连接成功之后,可以进行服务和特性的发现。 停止中心管理设备的扫描动作,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为iOS BLE4.0是支持一对多连接的),导致数据的混乱。
        //停止扫描
        [self.centralManager stopScan];
        // 设置外设的代理
        peripheral.delegate = self;
        // 根据UUID来寻找服务
        //[peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
        //外设发现服务,传nil代表不过滤,一次性读出外设的所有服务
        [peripheral discoverServices:nil];
    }
    

    /** 连接失败的回调 */

    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
        NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);
    }
    

    /** 断开连接 */

    - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
        NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);
        // 断开连接可以设置重新连接
        [central connectPeripheral:peripheral options:nil];
    }
    

    7、获取外围设备服务和特征
    peripheral调用discoverServices方法之后,在下面的回调函数中发现服务

    /** 发现服务 */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
        // 遍历出外设中所有的服务
        for (CBService *service in peripheral.services) {
             //查找服务中所有的特征
             [peripheral discoverCharacteristics:nil forService:service];
        }
    }
    

    peripheral调用查询对应服务下面的特征之后,会在下面的回调函数中返回

    /** 发现特征 */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
        if (error==nil) {
            for (CBCharacteristic *characteristic in service.characteristics){
                if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"49535343-8841-43F4-A8D4-ECBE34729BB3"]]){
                     self. characteristic = characteristic;
                }else if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"49535343-1E4D-4BD9-BA61-23C647249616"]]){
                     [peripheral setNotifyValue:TRUE forCharacteristic:characteristic];
                }
                self.peripheral = peripheral;
            }
        }
    }
    

    到现在打印所需要的所有内容都获取到了,就可以往打印机发送数据了

    8、从外围设备读取数据
    凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法,你可以判断是否 从外围设备读数据

    /** 接收到数据回调 */
    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
        NSData *data = characteristic.value; //获取到的数据
        NSLog(@"bbb-----%@----",data); //打印出来应该是<01a5>这样的数据,可以通过下面的方式去判断一些自己想要的逻辑
        Byte * resultByte = (Byte *)[data bytes];
        if(data.length>=1){
            if(resultByte[0]==16){ //16代表前两位的值
                NSLog(@"---打印机打开---");
            }else if (resultByte[0]==1){ //01
                NSLog(@"----打印机缺纸-----");
            }
        }
        //下面的处理方式我没处理过,大家可以试试
        //self.textFild.text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }
    

    9、向蓝牙设备写数据

        Byte byte[] = {0x1B,0x68};//打印机状态指令
        NSData *data = [[NSData alloc] initWithBytes:byte length:3];
        if(self.peripheral&&self.characteristic) {
            NSLog(@"发送获取状态指令");
            [peripheral writeValue:data forCharacteristic: characteristic type:CBCharacteristicWriteWithResponse];
        }
    

    这里说明怎么连接上一次或者之前连接的设备,可以保存之前设备的标识,进入App之后通过这个标识实例化服务来进行链接;通过这种方式不行的同学可以试试保存这个标识,下次进入的时候后台扫描设备,判断那个设备的标识和存储的一样,连接表示一样的那个...

    //这个是需要保存的标识
    NSString *connectId = peripheral.identifier.UUIDString;
    //进入App之后获取存储的标识进行初始化服务
    NSUUID *identifier = [[NSUUID UUID]initWithUUIDString: connectId];
    CBPeripheral *peri = [[self.centralManager retrievePeripheralsWithIdentifiers:@[identifier]] firstObject];
    if (peri == nil) {
        return;
    }
    if(peri.state==CBPeripheralStateConnected){
        [self alertMs:@"设备已被连接"];
        return;
    }
    [centralManager connectPeripheral:peri options:@{CBConnectPeripheralOptionNotifyOnConnectionKey : @YES}];
    

    关于蓝牙打印的知识暂时分享到这里,下面贴出参考的文章
    蓝牙的连接和数据的读写

    相关文章

      网友评论

        本文标题:iOS中蓝牙与打印机连接使用

        本文链接:https://www.haomeiwen.com/subject/lcxpzqtx.html