美文网首页灰苹果开发蓝牙知识
实践-佳博蓝牙打印机打印实现

实践-佳博蓝牙打印机打印实现

作者: 進无尽 | 来源:发表于2017-01-10 16:08 被阅读1446次

    前言

    最近项目中使用到了打印机,最后总算打印出自己想要打印的数据了,还算不错,做一个小结吧,希望对需要的朋友有些帮助。


    打印机

    我们使用的打印机是 《佳博ZH3080条码打印蓝牙标签机.....》,特殊说明一下,我使用的是标签模式(有标签模式和小票模式),而且使用标签模式的时候,如果打印机中的纸比较窄的话,每次打印,打印机都会回退纸张,这样就无法使用了,因为每次都是贴着边缘撕的纸,回退的话,纸就出不来了。必须选用宽大的纸,我使用的纸大概宽度有8CM

    效果

    工程设置

    不设置会直接Crash

    Paste_Image.png

    步骤

    • 链接上打印机
    • 组装要打印的数据
    • 设置打印机参数
    • 执行打印

    步骤解析和源码示例

    链接打印机

    打印机SDK头文件.png
    # ConnectViewController是Dome中提供的 带有 xib的链接类,继承自  CBController。CBController 的实现文件 .m是封装到SDK中的,我们不得而知,但是这里用到继承是为了 获取CBController 的方法和全局变量,下面会解释
    @interface ConnectViewController : CBController
    
    #CBController 的代理方法,
    ************************************************************
    
    #[self startScan]; 调用后会返回这个方法,在这个方法中刷新列表,而且数据都在  CBController 的中  devicesList  中返回所有搜素到的设备
    - (void)updateDiscoverPeripherals {
        [super updateDiscoverPeripherals];
        [devicesTableView reloadData];
    }
    #断开一个打印机,会触发这个代理方法来通知子类,
    - (void)updateMyPeripheralForDisconnect:(MyPeripheral *)myPeripheral {
       
    }
    #链接一个打印机,会触发这个代理方法来通知子类,
    - (void)updateMyPeripheralForNewConnected:(MyPeripheral *)myPeripheral {
    }
    *************************************************************
    - (void)viewDidAppear:(BOOL)animated {
            [self startScan];
     }
     
    #这个方法会执行  CBController 中搜索附近打印机设备的方法,并且以代理updateDiscoverPeripherals的方法把结果放到 devicesList中
    - (void)startScan {
        [super startScan];
    }
    
    # 在表的  numberOfRowsInSection  方法中过滤掉未识别的设备
     for (MyPeripheral *tmpPeripheral in devicesList) {
         if (!tmpPeripheral.advName) {
            [devicesList removeObject:tmpPeripheral];
           }
     }
    return [devicesList count];
    

    组装要打印的数据

     #最终的效果如下
     NSArray *textArray = @[@"领料单详情",
                               @"领料人:张笑傲",
                               @"2016-12-16",
                               @"----------------------------------",
                               @"商品名称     数量      单位",
                               @"西瓜         11        斤",
                               @"(领取生产日期为,\n严格核对严格核对严格核对)",
                               @"西瓜         11        斤",
                               @"(领取生产日期为,严格\n核对严格核对严格核对)",
                               @"西瓜         11        斤",
                               @"(领取生产日期为,严格核\n对严格核对严格核对)",
                               @"西瓜         11        斤",
                               @"(领取生产日期为,严格核对严格核对严格核对)",
                               @"西瓜         11        斤",
                               @"(领取生产日期为,严格核对严格核对严格核对)",
                               @"-----------------------------------",
                               @"商品种类数:5",];
    
    
    #根据一个字典,组装数据
    - (void)initPrintStrWith :(NSDictionary *)dataDic;
      {
        [printStrArray removeAllObjects];
        [printStrArray addObject:@"领料单详情"];
        [printStrArray addObject:[NSString stringWithFormat:@"领料人:%@",dataDic[@"cgd"][@"zdperson"]]];
        [printStrArray addObject:dataDic[@"cgd"][@"lldate"]];
        [printStrArray addObject:@"--------------------------------------"];
        [printStrArray addObject:[self getPrintString:@"商品名称" :@"数量" tail:@"单位"]];
        NSArray *listArray = dataDic[@"xqlist"];
        for (int i = 0; i<listArray.count; i++) {
            NSDictionary *dic = listArray[i];
            NSString *name = dic[@"hpname"];
            NSString *numer = [dic[@"hpnumber"] stringValue];
            NSString *danwei = dic[@"dwname"];
            #组成固定长度的字符串,中间填充 空格
            NSString *inforStr = [self getPrintString:name :numer tail:danwei];
            [printStrArray addObject:inforStr];
            if ([self recursionSubStr:dic[@"hpscrq"]]) {
                #递归的方法截字符串
                [printStrArray addObjectsFromArray:[self recursionSubStr:[dic[@"hpscrq"] stringByReplacingOccurrencesOfString:@"#" withString:@""]]];
            }
        }
        [printStrArray addObject:@"--------------------------------------"];
        [printStrArray addObject:[NSString stringWithFormat:@"商品种类数:%lu",(unsigned long)listArray.count]];
        
    }
    
    #判断中英混合的的字符串长度,
    #如果你的打印效果是同一种类型的文字当然可以,但如果同时包含字母,汉子,数字等,那么用length计算的长度就不准确了,因为字母,汉子的编码不同,字节数是不同的,所以要转换成Unicode编码统一的计算。**
    - (int)convertToInt:(NSString*)strtemp
    {
        int strlength = 0;
        char* p = (char*)[strtemp cStringUsingEncoding:NSUnicodeStringEncoding];
        for (int i=0 ; i<[strtemp lengthOfBytesUsingEncoding:NSUnicodeStringEncoding] ;i++) {
            if (*p) {
                p++;
                strlength++;
            }
            else {
                p++;
            }
        }
        return strlength;
    }
    #三部分数据拼成固定长度Str     中间填充空格组装成固定长度的字符串
    - (NSString *)getPrintString:(NSString *)leader  :(NSString *)middle    tail:(NSString *)tail
    {
        static int TOTAL = 30;//这里是根据你的纸张宽度试验出来的一个合适的总字数
        
        NSMutableString *printString = [NSMutableString new];
        [printString appendString:leader];
        int lenderLen = [self convertToInt:leader];
        
        if (tail && middle) {
            int midddleLen = [self convertToInt:middle];
            int tailLen = [self convertToInt:tail];
            
            int detal = (int)(TOTAL - lenderLen - tailLen - midddleLen)/2;
            for (int i = 0; i < detal; i ++) {
                [printString appendString:@" "];
            }
            [printString appendString:middle];
            for (int i = 0; i < detal; i ++) {
                [printString appendString:@" "];
            }
            [printString appendString:tail];
        }
        return printString;
    }
    #递归的方法分割字符串,     把比较长的字符串截成几段固定长度的字符串后放入数组中
    - (NSArray *)recursionSubStr:(NSString *)origaneStr
    {
        
        NSMutableArray *strA = [[NSMutableArray alloc]initWithCapacity:0];
        if (origaneStr.length<30) {
            [strA addObject:origaneStr];
            return strA;   
        }
        [strA addObject:[origaneStr substringToIndex:29]];
        [strA  addObjectsFromArray:[self recursionSubStr:[origaneStr substringFromIndex:29]]];
        return strA;
    }
    

    设置打印机参数

    - (void)printAction;
    {
        if (printStrArray.count==0) {
            return;
        }
        
        TscCommand *tscCmd = [[TscCommand alloc] init];
        #设置为YES才能打印
        [tscCmd setHasResponse:YES];
        #设置打印纸的打印尺寸  从打印纸的右边开始计算宽度 设置的尺寸要小于实际的宽度才能在左边留白   高度为打印区域的高度     都是 mm 单位,尺寸为实际打印出的尺寸(可以用尺子测量)
        [tscCmd addSize:73 :((int)(printStrArray.count+3)*3+10)];
        #设置标签间隙尺寸  没什么用
        [tscCmd addGapWithM:10   withN:10];
        #不设置会有异常,不设置第一次打印出现很大的空白空隙
        [tscCmd addReference:10
                            :10];
        #打印速度
        [tscCmd addSpeed:4];
        [tscCmd addDensity:8];
        #0正向  1反向(尾部的先打印出来)
        [tscCmd addDirection:0];
        [tscCmd addComonCommand];
        [tscCmd addCls];
        # x,y 值   目测是  1/100 厘米  x,从左到右依次增大,y从上到下依次增大
        NSMutableArray *xArray = [[NSMutableArray alloc]initWithCapacity:0];
        for (int i = 0; i<printStrArray.count; i++) {
            if (i==0) {
                [xArray addObject:@"200"];
            }else{
                [xArray addObject:@"0"];
            }
        } 
        #设置每条要打印的字符串的 x,y 值
        for (int i=0; i<printStrArray.count;i++) {
            
            [tscCmd addTextwithX:[xArray[i] intValue]
                           withY:(i*30)
                        withFont:@"TSS24.BF2"
                    withRotation:0
                       withXscal:1
                       withYscal:1
                        withText:printStrArray[i]];
        }
        #打印二维码
        [tscCmd addQRCode:380
                         :(15)
                         :@"L"
                         :4
                         :@"A"
                         :0
                         :allDataDic[@"cgd"][@"ewmcode"]];
        
        #不在最后打印 .  底部留白太少,撕下来时会撕不完整,打印一个  .  在底部即可达到底部留白的效果,
        #而且有时候,不在最后打印  .\n  很多内容打印不出来,不知道为什么。
        [tscCmd addTextwithX:20
                       withY:((int)(printStrArray.count)*30+5)
                    withFont:@"TSS24.BF2"
                withRotation:0
                   withXscal:1
                   withYscal:1
                    withText:@".\n"];
    
        #print 执行打印命令
        [tscCmd addPrint:1 :1];
    }
    

    执行打印

     //打印操作
     - (void)NewRightNavItemClick
      {
        
        if([[BLKWrite Instance] isConnecting]){
           [printManager initPrintStrWith:intBackDic :YES];
           [printManager printAction];
        }
        else{
            [[BLKWrite Instance] setBWiFiMode:NO];
            [self.navigationController pushViewController:[[ConnectViewController alloc] initWithNibName:nil bundle:nil] animated:YES];
          
        **************************************************************
        #这里有一个值得注意的地方,如果链接了打印机,还想点击进入链接页面,展示出链接的打印机信息,需要使用下面的方法,
        #即进入上次创建的哪个视图,不能新建,新建的话会遇到SDK报错Alert弹框。这里是用了单例保存了上次新建的链接视图。
        // [[BLKWrite Instance] setBWiFiMode:NO];
        // AppDelegate *dele = [UIApplication sharedApplication].delegate;
        // [self.navigationController pushViewController:dele.mConnBLE animated:YES];
         #AppDelegate中
         @property (strong, nonatomic) ConnectViewController *mConnBLE;
         self.mConnBLE = [[ConnectViewController alloc] initWithNibName:nil bundle:nil];
        }
    }
    

    有帮助的文章
    iOS中的蓝牙开发
    iOS蓝牙原生封装,助力智能硬件开发

    相关文章

      网友评论

      • fero2004:作者知道怎么获得打印机状态吗?他有个查询状态的函数,但是没有返回值呢?

        /**
        * 方法说明:查询打印机状态<ESC>!?
        *询问打印机状态指令为立即响应型指令,该指令控制字符是以<ESC> (ASCII 27=0x1B, escape字符)为控制字符.!(ASCII 33=0x21),?(ASCII 63=0x3F)
        *即使打印机在错误状态中仍能透过 RS-232 回传一个 byte 资料来表示打印机状态,若回传值为 0 则表示打印
        *机处于正常的状态
        * @return void
        */
        -(void) queryPrinterStatus;
      • 草原野马:打印成功的回调,在哪里啊,谁知道。
        tree_73a4:用sdk 到时候会很惨
        fero2004:同求,lz解决了吗?
        silver_b7ea:同求,你解决了吗?
      • eeb00f1db215:能共享一下案例或者发一份sdk给我吗?
      • 草原野马:解决了没有,指令也打印出来了。
        tree_73a4:@草原野马 :disappointed_relieved:
        草原野马:@tree_73a4 嗯,弄好了,官网给的demo就不行,你们的菜名过长换行,是怎么换的啊。
        tree_73a4:-[CBPeripheral writeValue:forCharacteristic:type:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreBluetooth/CoreBluetooth-352.1/CoreBluetooth/CBPeripheral.m:375
      • tree_73a4:为什么指令也打印出来了
        子非鱼7868:解决了没有 我的也是
        草原野马:解决了没有,我的demo也是指令都打印出来了。
        草原野马:解决了没有,指令也打印出来了。
      • 97565376120e:大神求demo和SDK
      • 逍遥庄主:大神,我们也准备做蓝牙打印,买了一台佳博zh3080,关于你说的demo和SDK是从哪里下载的呢。他们官网没找到
        逍遥庄主:@就是很随意哦 我只能告诉你,给厂家打电话,要技术电话邮箱,然后让他给你发demo,或者SDK文档
        就是很随意哦:同求demo 啊
      • CodeRookie:佳博的怎么打印图片啊
      • 无赖_V:大神求助,我设置了App communicates using CoreBluetooth, 但是苹果审核不通过! 要怎么解决!!
        進无尽:@小召95 推荐你看我的另一篇文章,里面有解决方案,可以一试:http://www.jianshu.com/p/33c728159d4c
        无赖_V:@芳梅 Your app declares support for bluetooth-central in the UIBackgroundModes key in your Info.plist but does not provide Bluetooth Low Energy functionality. The Bluetooth Background modes are for apps that communicate to other devices using Bluetooth Low Energy and the Core Bluetooth framework.

        Next Steps

        To resolve this issue, please revise your app to add support for Bluetooth Low Energy communication through Core Bluetooth in your app or remove the bluetooth- values from the UIBackgroundModes key.
        進无尽:@小召95 是开启了后台模式吗?拒绝理由是什么
      • 小栗子二号:你好,当我设置打印二维码位置时,总是无效,知道是怎么回事吗
      • 马拉古_:请问佳博的sdk 有提供api 使用UUID连接打印机吗
        - (void)configureDeviceInformationServiceUUID: (NSString *)UUID1 UUID2:(NSString *)UUID2;这个方法具体是做什么用的?
        進无尽:@奔跑_D_古力 这个好像没有:relaxed:
      • ceed19465bd4:专业生产开发蓝牙打印机、标签机、热敏打印机,提供开发技术支持及DEMO,需要的联系,QQ:81617129,T:17701729330
      • 72fe0b2ff6f6:大神 我用的是佳博GP-L80160l 打印完成后怎么实现自动切刀 还有就是 打印图片的时候声音特别大 求大神解决
        進无尽:加 \n就可以自动换行,声音很大可能跟打印机有关吧
      • 哥斯拉不拉:TSS24.BF2 这个 相当于多大字体呢?
      • 9cdf7a3803a9:大神 求助 蓝牙标签打印这个 不太懂 能不能 加个QQ 893549897 详细说明下 或者发个demo 看看 拜谢了!
        72fe0b2ff6f6:打印完成后切刀指令怎么做
        進无尽:@知秋丶一叶_f8a0 你好,有什么问题在这讨论吧,扣扣可能没时间聊的哦,你留言,如果我知道我就回答下哦:relieved:

      本文标题:实践-佳博蓝牙打印机打印实现

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