美文网首页good
iOS 打印小票

iOS 打印小票

作者: 高乔人 | 来源:发表于2018-09-13 11:49 被阅读44次
#import <CoreBluetooth/CoreBluetooth.h>
#ifndef JWBluetoothBlocks_h
#define JWBluetoothBlocks_h

 // 打印流程:   搜索蓝牙外设 -->连接蓝牙  -->搜索服务 -->搜索特性 --> 
写入数据 -->打印成功
// 连接上打印机,需要判断扫描的阶段,如果直接进行打印会有可能导致 没有搜索到特性阶段,调用打印API是打印不成功的,所以等待特性回调之后打印 万无一失

typedef NS_ENUM(NSInteger, JWScanStage) {
JWScanStageConnection = 0,            //蓝牙连接阶段
JWScanStageServices,             //服务阶段
JWScanStageCharacteristics,     //特性阶段   //注意  只有到达特性阶段才能进行打印
};


 /**
 蓝牙外设扫描结束成功之后的block

 @param peripherals 蓝牙外设列表
 @param rssis 蓝牙信号强度
 */
typedef void(^JWScanPerpheralsSuccess)(NSArray<CBPeripheral *> 
*peripherals,NSArray<NSNumber *> *rssis);

/**
 扫描失败的block
 @param status 失败的枚举  CBManagerStatePoweredOn 是正常使用的
 */
typedef void(^JWScanPeripheralFailure)(CBManagerState status);

/**
连接完成的block
@param perpheral 要连接的蓝牙外设
*/
typedef void(^JWConnectPeripheralCompletion)(CBPeripheral 
*perpheral, NSError *error);


/**
 蓝牙断开连接
@param perpheral 蓝牙外设
@param error        错误
*/
typedef void(^JWDisconnectPeripheralBlock)(CBPeripheral *perpheral, NSError *error);


/**
 打印之后回调

@param completion 是否完成打印
@param peripheral 外设
@param errorString 出错的原因
*/
typedef void(^JWPrintResultBlock)(BOOL completion, CBPeripheral *peripheral,NSString * errorString);



#endif /* JWBluetoothBlocks_h */

////////////////////////////////////////////////
 #import <Foundation/Foundation.h>
 #import "JWBluetoothBlocks.h"
 #import "ProgressShow.h"
 #import "JWPrinter.h"


@interface JWBluetoothManage : NSObject
//单例方法
+ (instancetype)sharedInstance;

@property (nonatomic, strong,readonly)CBPeripheral                *connectedPerpheral;    //  当前连接的外设蓝牙

/**
开始扫描蓝牙外设,block方式返回结果
@param success 扫描成功的回调
@param failure 扫描失败的回调
*/
  - (void)beginScanPerpheralSuccess:(JWScanPerpheralsSuccess)success failure:(JWScanPeripheralFailure)failure;

/**
  连接蓝牙外设,连接成功后会停止扫描蓝牙外设,block方式返回结果

@param peripheral 要连接的蓝牙外设
@param completion 连接成功回调(有成功 跟失败判断error是否为空就可以了)
 */
 - (void)connectPeripheral:(CBPeripheral *)peripheral completion:(JWConnectPeripheralCompletion)completion;

/**
 自动连接上次连接的蓝牙
 //因为使用自动连接的话同样也会扫描设备  所以如果单一只是想要连接外设,用此API就可以了

@param completion 连接成功回调(有成功 跟失败判断error是否为空就可以了)
 */
- (void)autoConnectLastPeripheralCompletion:(JWConnectPeripheralCompletion)completion;

/**
  需要判断JWScanStage来进行打印,如果只是连接 不需要关心,
 */
@property (nonatomic, assign) JWScanStage stage;
 /**
 断开连接的block
 */
 @property (nonatomic, copy) JWDisconnectPeripheralBlock disConnectBlock;


/**
 停止扫描设备
 */
- (void)stopScanPeripheral;

/**
 取消某个设备的连接

@param peripheral 设备
*/
- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral;

/**
 进行打印

 @param data 打印数据
 @param result 结果回调
 */
 - (void)sendPrintData:(NSData *)data completion:(JWPrintResultBlock)result;


@end

接下来是.m文件。

    #import "JWBluetoothManage.h"

    static JWBluetoothManage * manage = nil;

    @interface JWBluetoothManage () <CBCentralManagerDelegate,CBPeripheralDelegate>

    @property (nonatomic, strong)   CBCentralManager             *centralManager;           //  服务设备管理器

    @property (nonatomic, strong)   NSMutableArray               *peripherals;             //  搜索到的蓝牙设备数组
    @property (nonatomic, strong)   NSMutableArray               *rssis;                   //  搜索到的蓝牙设备列表信号强度数组
    @property (nonatomic, strong)   NSMutableArray               *printeChatactersArray;   //  可以打印的的特性数组

    @property (nonatomic, copy)     JWScanPerpheralsSuccess        scanPerpheralSuccess;   // 扫描设备成功的回调
    @property (nonatomic, copy)     JWScanPeripheralFailure        scanPerpheralFailure;   // 扫描设备失败的回调
    @property (nonatomic, copy)     JWConnectPeripheralCompletion  connectCompletion;      // 连接完成的回调
    @property (nonatomic, copy)     JWPrintResultBlock              printResult;           // 打印结果的回调

    //此参数是为了计算打印有没有出错
    @property (nonatomic, assign)   BOOL                         autoConnect;              // 是否自动连接
    @property (nonatomic, assign)   NSInteger                    writeCount;               // 写入次数
    @property (nonatomic, assign)   NSInteger                    responseCount;            //  返回次数

    @end

    @implementation JWBluetoothManage

    #pragma mark - Singleton Medth

    + (instancetype)sharedInstance{
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manage = [[JWBluetoothManage alloc] init];
        });
        return manage;
    }
    - (instancetype)init{
        if (self = [super init]) {
            [self _initBluetooth];
        }
        return self;
    }
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manage = [super allocWithZone:zone];
        });
        
        return manage;
    }
    - (void) _initBluetooth{
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
        [self.peripherals removeAllObjects];
        [self.rssis removeAllObjects];
        [self.printeChatactersArray removeAllObjects];
        _connectedPerpheral = nil;
    }
    #pragma mark - Bluetooth Medthod
    //开始搜索
    - (void)beginScanPerpheralSuccess:(JWScanPerpheralsSuccess)success failure:(JWScanPeripheralFailure)failure{
        //block 赋值
        _scanPerpheralSuccess = success;
        _scanPerpheralFailure = failure;
        if (_centralManager.state == CBManagerStatePoweredOn) {
            //开启搜索
            NSLog(@"开启扫描");
            [_centralManager scanForPeripheralsWithServices:nil options:nil];
            return;
        }
        //防止因为权限问题造成BUG
        [self _initBluetooth];
    }
    #pragma mark - CBCentralManagerDelegate Medthod
    //权限改变重新搜索设备
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central{
        if (central.state != CBManagerStatePoweredOn) {
            if (_scanPerpheralFailure) {
                _scanPerpheralFailure(central.state);
            }
        }else{
            [central scanForPeripheralsWithServices:nil options:nil];
        }
    }

    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{
        NSLog(@"扫描中....");
        if (peripheral.name.length <= 0) {
            return ;
        }
        
        if (_peripherals.count == 0) {
            [_peripherals addObject:peripheral];
            [_rssis addObject:RSSI];
        } else {
            __block BOOL isExist = NO;
            //去除相同设备  UUIDString  是每个外设的唯一标识
            [_peripherals enumerateObjectsUsingBlock:^(CBPeripheral *   _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                CBPeripheral *per = [_peripherals objectAtIndex:idx];
                if ([per.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]) {
                    isExist = YES;
                    [_peripherals replaceObjectAtIndex:idx withObject:peripheral];
                    [_rssis replaceObjectAtIndex:idx withObject:RSSI];
                }
            }];
            if (!isExist) {
                [_peripherals addObject:peripheral];
                [_rssis addObject:RSSI];
            }
        }
        if (_scanPerpheralSuccess) {
            _scanPerpheralSuccess(_peripherals,_rssis);
        }
        
        if (_autoConnect) {
            NSString * uuid = GetLastConnectionPeripheral_UUID();
            if ([peripheral.identifier.UUIDString isEqualToString:uuid]) {
                peripheral.delegate = self;
                [_centralManager connectPeripheral:peripheral options:nil];
            }
        }
    }
    #pragma mark - 连接外设 Medthod
    - (void)connectPeripheral:(CBPeripheral *)peripheral completion:(JWConnectPeripheralCompletion)completion{
        _connectCompletion = completion;
        if (_connectedPerpheral) {
            
            [self cancelPeripheralConnection:_connectedPerpheral];
        }
        [self connectPeripheral:peripheral];
    }
    //连接外设设置代理
    - (void)connectPeripheral:(CBPeripheral *)peripheral{
        [_centralManager connectPeripheral:peripheral options:nil];
        peripheral.delegate = self;
    }
    - (void)autoConnectLastPeripheralCompletion:(JWConnectPeripheralCompletion)completion{
        _connectCompletion = completion;
        _autoConnect = YES;
        
        if (_centralManager.state == CBManagerStatePoweredOn) {
            //开启搜索
            NSLog(@"开启扫描");
            [_centralManager scanForPeripheralsWithServices:nil options:nil];
        }
        
    }
    - (void)cancelPeripheralConnection:(CBPeripheral *)peripheral{
        if (!peripheral) {
            return;
        }
        //去除次自动连接
        RemoveLastConnectionPeripheral_UUID();
        
        [_centralManager cancelPeripheralConnection:peripheral];
        _connectedPerpheral = nil;
        //取消连接 清楚可打印输入
        [_printeChatactersArray removeAllObjects];
    }
    - (void)stopScanPeripheral{
        [_centralManager stopScan];
    }

    #pragma mark - 连接外设代理 Medthod
    //成功连接
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
        //当前设备赋值
        _connectedPerpheral = peripheral;
        //存入标识符  下次自动
        SetLastConnectionPeripheral_UUID(peripheral.identifier.UUIDString);
        //链接成功 停止扫描
        [_centralManager stopScan];
        if (_connectCompletion) {
            _connectCompletion(peripheral,nil);
        }
        _stage = JWScanStageConnection;
        peripheral.delegate = self;
        //发现服务 扫描服务
        [peripheral discoverServices:nil];
    }
    //连接失败
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
        if (_connectCompletion) {
            _connectCompletion(peripheral,error);
        }
        _stage = JWScanStageConnection;
    }
    //断开连接
    - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
        _connectedPerpheral = nil;
        [_printeChatactersArray removeAllObjects];
        
        if (_disConnectBlock) {
            _disConnectBlock(peripheral,error);
        }
        _stage = JWScanStageConnection;
    }
    #pragma mark 蓝牙服务代理
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
        if (error) {
             NSLog(@"发现服务出错 错误原因-%@",error.domain);
        }else{
            for (CBService *service in peripheral.services) {
                [peripheral discoverCharacteristics:nil forService:service];
            }
        }
        _stage = JWScanStageServices;
    }
    #pragma mark 蓝牙服务特性代理
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
        if (error) {
            NSLog(@"发现特性出错 错误原因-%@",error.domain);
        }else{
            for (CBCharacteristic *character in service.characteristics) {
                CBCharacteristicProperties properties = character.properties;
                if (properties & CBCharacteristicPropertyWrite) {
                    NSDictionary *dict = @{@"character":character,@"type":@(CBCharacteristicWriteWithResponse)};
                    [_printeChatactersArray addObject:dict];
                }
            }
        }
        if (_printeChatactersArray.count > 0) {
            _stage = JWScanStageCharacteristics;
        }
    }
    #pragma mark 写入数据  跟block
    // 发送数据时,需要分段的长度,部分打印机一次发送数据过长就会乱码,需要分段发送。这个长度值不同的打印机可能不一样,你需要调试设置一个合适的值(最好是偶数)
    #define kLimitLength    146

    - (void)sendPrintData:(NSData *)data completion:(JWPrintResultBlock)result{
        if (!self.connectedPerpheral) {
            if (result) {
                result(NO,_connectedPerpheral,@"未连接蓝牙设备");
            }
            return;
        }
        if (self.printeChatactersArray.count == 0) {
            if (result) {
                result(NO,_connectedPerpheral,@"该蓝牙设备不支持写入数据");
            }
            return;
        }
        NSDictionary *dict = [_printeChatactersArray lastObject];
        _writeCount = 0;
        _responseCount = 0;
        
        // 如果kLimitLength 小于等于0,则表示不用分段发送
        if (kLimitLength <= 0) {
            _printResult = result;
            [_connectedPerpheral writeValue:data forCharacteristic:dict[@"character"] type:[dict[@"type"] integerValue]];
            _writeCount ++;
            return;
        }
        
        if (data.length <= kLimitLength) {
            _printResult = result;
            [_connectedPerpheral writeValue:data forCharacteristic:dict[@"character"] type:[dict[@"type"] integerValue]];
            _writeCount ++;
        } else {
            //分段打印
            NSInteger index = 0;
            for (index = 0; index < data.length - kLimitLength; index += kLimitLength) {
                NSData *subData = [data subdataWithRange:NSMakeRange(index, kLimitLength)];
                [_connectedPerpheral writeValue:subData forCharacteristic:dict[@"character"] type:[dict[@"type"] integerValue]];
                _writeCount++;
            }
            _printResult = result;
            NSData *leftData = [data subdataWithRange:NSMakeRange(index, data.length - index)];
            if (leftData) {
                [_connectedPerpheral writeValue:leftData forCharacteristic:dict[@"character"] type:[dict[@"type"] integerValue]];
                _writeCount++;
            }
        }
    }

    - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
        if (!_printResult) {
            return;
        }
        _responseCount ++;
        if (_writeCount != _responseCount) {
            return;
        }
        if (error) {
            _printResult(NO,_connectedPerpheral,@"发送失败");
        } else {
            _printResult(YES,_connectedPerpheral,@"已成功发送至蓝牙设备");
        }
    }

    #pragma mark - init containers

    - (NSMutableArray *)peripherals{
        if (!_peripherals) {
            _peripherals = @[].mutableCopy;
        }
        return _peripherals;
    }
    - (NSMutableArray *)rssis{
        if (!_rssis) {
            _rssis = @[].mutableCopy;
        }
        return _rssis;
    }
    -(NSMutableArray *)printeChatactersArray{
        if (!_printeChatactersArray) {
            _printeChatactersArray = @[].mutableCopy;
        }
        return _printeChatactersArray;
    }

    NSString * GetLastConnectionPeripheral_UUID(){
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        NSString *uuid = [userDefaults objectForKey:@"BluetoothPeripheral_uuid"];
        return uuid;
    }

    void SetLastConnectionPeripheral_UUID(NSString * uuid){
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        [userDefaults setObject:uuid forKey:@"BluetoothPeripheral_uuid"];
        [userDefaults synchronize];
    }
    void RemoveLastConnectionPeripheral_UUID(){
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        [userDefaults removeObjectForKey:@"BluetoothPeripheral_uuid"];
        [userDefaults synchronize];
    }
    @end

控制文字对齐方式,字号,信息等。

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>
#import "UIImage+Bitmap.h"

typedef NS_ENUM(NSInteger, HLPrinterStyle) {
    HLPrinterStyleDefault,
    HLPrinterStyleCustom
};

/** 文字对齐方式 */
typedef NS_ENUM(NSInteger, HLTextAlignment) {
    HLTextAlignmentLeft = 0x00,
    HLTextAlignmentCenter = 0x01,
    HLTextAlignmentRight = 0x02
};

/** 字号 */
typedef NS_ENUM(NSInteger, HLFontSize) {
    HLFontSizeTitleSmalle = 0x00,
    HLFontSizeTitleMiddle = 0x11,
    HLFontSizeTitleBig = 0x22
};

@interface JWPrinter : NSObject
/**
 添加单行标题,默认字号是小号字体

 @param text 标题名称
 @param alignment 标题对齐方式
 */
- (void)appendText:(NSString *)text alignment:(HLTextAlignment)alignment;

/**
 添加单行标题

 @param text 标题名称
 @param alignment 标题对齐方式
 @param fontSize 标题字号
 */
- (void)appendText:(NSString *)text alignment:(HLTextAlignment)alignment fontSize:(HLFontSize)fontSize;

/**
 添加单行信息,左边名称(左对齐),右边实际值(右对齐),默认字号是小号。

 @param title 名称
 @param value 实际值
 */
- (void)appendTitle:(NSString *)title value:(NSString *)value;
/**
 添加单行信息,左边名称(左对齐),右边实际值(右对齐)。

 @param title 名称
 @param value 实际值
 @param fontSize 字号大小
 警告:因字号和字体与iOS中字体不一致,计算出来有误差,所以建议用在价格方面
 */
- (void)appendTitle:(NSString *)title value:(NSString *)value fontSize:(HLFontSize)fontSize;
/**
 设置单行信息,左标题,右实际值
 @提醒 该方法的预览效果与实际效果误差较大,请以实际打印小票为准

 @param title 标题
 @param value 实际值
 @param offset 实际值偏移量
 */
- (void)appendTitle:(NSString *)title value:(NSString *)value valueOffset:(NSInteger)offset;

/**
 设置单行信息,左标题,右实际值
 @提醒 该方法的预览效果与实际效果误差较大,请以实际打印小票为准

 @param title 标题
 @param value 实际值
 @param offset 实际值偏移量
 @param fontSize 字号
 */
- (void)appendTitle:(NSString *)title value:(NSString *)value valueOffset:(NSInteger)offset fontSize:(HLFontSize)fontSize;

/**
 添加选购商品信息标题,一般是三列,名称、数量、单价

 @param left  左标题
 @param middle 中间标题
 @param right 右标题
 @param isTitle 是否是标题
 */
- (void)appendLeftText:(NSString *)left middleText:(NSString *)middle rightText:(NSString *)right isTitle:(BOOL)isTitle;

/**
 添加图片,一般是添加二维码或者条形码
 ⚠️提醒:这种打印图片的方式,是自己生成图片,然后用位图打印
 @param image 图片
 @param alignment 图片对齐方式
 @param maxWidth 图片的最大宽度,如果图片过大,会等比缩放
 */
- (void)appendImage:(UIImage *)image alignment:(HLTextAlignment)alignment maxWidth:(CGFloat)maxWidth;

/**
 添加条形码图片
 ⚠️提醒:这种打印条形码的方式,是自己生成条形码图片,然后用位图打印图片

 @param info 条形码中包含的信息,默认居中显示,最大宽度为300。如果大于300,会等比缩放。
 */
- (void)appendBarCodeWithInfo:(NSString *)info;

/**
 添加条形码图片
⚠️提醒:这种打印条形码的方式,是自己生成条形码图片,然后用位图打印图片
 @param info 条形码中的信息
 @param alignment 图片对齐方式
 @param maxWidth 图片最大宽度
 */
- (void)appendBarCodeWithInfo:(NSString *)info alignment:(HLTextAlignment)alignment maxWidth:(CGFloat)maxWidth;

/**
  添加二维码
✅推荐:这种方式使用的是打印机的指令生成二维码并打印机,所以比较推荐这种方式
 @param info 二维码中的信息
 @param size 二维码的大小 取值范围1 <= size <= 16
 */
- (void)appendQRCodeWithInfo:(NSString *)info size:(NSInteger)size;

/**
 添加二维码
 ✅推荐:这种方式使用的是打印机的指令生成二维码并打印机,所以比较推荐这种方式
 @param info 二维码中的信息
 @param size 二维码大小,取值范围 1 <= size <= 16
 @param alignment 设置图片对齐方式
 */
- (void)appendQRCodeWithInfo:(NSString *)info size:(NSInteger)size alignment:(HLTextAlignment)alignment;

/**
 添加二维码图片
⚠️提醒:这种打印条二维码的方式,是自己生成二维码图片,然后用位图打印图片
 @param info 二维码中的信息
 */
- (void)appendQRCodeWithInfo:(NSString *)info;

/**
 添加二维码图片
 ⚠️提醒:这种打印条二维码的方式,是自己生成二维码图片,然后用位图打印图片
 @param info  二维码中的信息
 @param centerImage 二维码中间的图片
 @param alignment 对齐方式
 @param maxWidth 二维码的最大宽度
 */
- (void)appendQRCodeWithInfo:(NSString *)info centerImage:(UIImage *)centerImage alignment:(HLTextAlignment)alignment maxWidth:(CGFloat )maxWidth;

/**
 *  添加一条分割线,like this:---------------------------
 */
- (void)appendSeperatorLine;

/**
 添加底部信息

 @param footerInfo 不填默认为 谢谢惠顾,欢迎下次光临!
 */
- (void)appendFooter:(NSString *)footerInfo;

/**
 换行符
 */
- (void)appendNewLine;

/**
 获取最终的data
 
 @return 最终的data
 */
- (NSData *)getFinalData;


@end

JWPrinter.m文件如下:

#import "JWPrinter.h"

#define kMargin 20
#define kPadding 2
#define kWidth 320

@interface JWPrinter ()

/** 将要打印的排版后的数据 */
@property (strong, nonatomic)   NSMutableData            *printerData;

@end

@implementation JWPrinter
- (instancetype)init
{
self = [super init];
if (self) {
    [self defaultSetting];
}
return self;
}

- (void)defaultSetting
{
_printerData = [[NSMutableData alloc] init];

// 1.初始化打印机
Byte initBytes[] = {0x1B,0x40};
[_printerData appendBytes:initBytes length:sizeof(initBytes)];
// 2.设置行间距为1/6英寸,约34个点
// 另一种设置行间距的方法看这个 @link{-setLineSpace:}
Byte lineSpace[] = {0x1B,0x32};
[_printerData appendBytes:lineSpace length:sizeof(lineSpace)];
// 3.设置字体:标准0x00,压缩0x01;
Byte fontBytes[] = {0x1B,0x4D,0x00};
[_printerData appendBytes:fontBytes length:sizeof(fontBytes)];

}

#pragma mark - -------------基本操作----------------
/**
*  换行
*/
- (void)appendNewLine
{
Byte nextRowBytes[] = {0x0A};
[_printerData appendBytes:nextRowBytes length:sizeof(nextRowBytes)];
}

/**
*  回车
*/
- (void)appendReturn
{
Byte returnBytes[] = {0x0D};
[_printerData appendBytes:returnBytes length:sizeof(returnBytes)];
}

/**
*  设置对齐方式
*
*  @param alignment 对齐方式:居左、居中、居右
*/
- (void)setAlignment:(HLTextAlignment)alignment
{
Byte alignBytes[] = {0x1B,0x61,alignment};
[_printerData appendBytes:alignBytes length:sizeof(alignBytes)];
}

/**
*  设置字体大小
*
*  @param fontSize 字号
*/
- (void)setFontSize:(HLFontSize)fontSize
{
Byte fontSizeBytes[] = {0x1D,0x21,fontSize};
[_printerData appendBytes:fontSizeBytes length:sizeof(fontSizeBytes)];
}

/**
*  添加文字,不换行
*
*  @param text 文字内容
*/
- (void)setText:(NSString *)text
{
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [text dataUsingEncoding:enc];
[_printerData appendData:data];
}

/**
*  添加文字,不换行
*
*  @param text    文字内容
*  @param maxChar 最多可以允许多少个字节,后面加...
*/
- (void)setText:(NSString *)text maxChar:(int)maxChar
{
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [text dataUsingEncoding:enc];
if (data.length > maxChar) {
    data = [data subdataWithRange:NSMakeRange(0, maxChar)];
    text = [[NSString alloc] initWithData:data encoding:enc];
    if (!text) {
        data = [data subdataWithRange:NSMakeRange(0, maxChar - 1)];
        text = [[NSString alloc] initWithData:data encoding:enc];
    }
    text = [text stringByAppendingString:@"..."];
}
[self setText:text];
}

/**
*  设置偏移文字
*
*  @param text 文字
*/
- (void)setOffsetText:(NSString *)text
{
// 1.计算偏移量,因字体和字号不同,所以计算出来的宽度与实际宽度有误差(小字体与22字体计算值接近)
NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:22.0]};
NSAttributedString *valueAttr = [[NSAttributedString alloc] initWithString:text attributes:dict];
int valueWidth = valueAttr.size.width;

// 2.设置偏移量
[self setOffset:368 - valueWidth];

// 3.设置文字
[self setText:text];
}

/**
*  设置偏移量
*
*  @param offset 偏移量
*/
- (void)setOffset:(NSInteger)offset
{
NSInteger remainder = offset % 256;
NSInteger consult = offset / 256;
Byte spaceBytes2[] = {0x1B, 0x24, remainder, consult};
[_printerData appendBytes:spaceBytes2 length:sizeof(spaceBytes2)];
}

/**
*  设置行间距
*
*  @param points 多少个点
*/
- (void)setLineSpace:(NSInteger)points
{
//最后一位,可选 0~255
Byte lineSpace[] = {0x1B,0x33,60};
[_printerData appendBytes:lineSpace length:sizeof(lineSpace)];
}

/**
*  设置二维码模块大小
*
*  @param size  1<= size <= 16,二维码的宽高相等
*/
- (void)setQRCodeSize:(NSInteger)size
{
Byte QRSize [] = {0x1D,0x28,0x6B,0x03,0x00,0x31,0x43,size};
//    Byte QRSize [] = {29,40,107,3,0,49,67,size};
[_printerData appendBytes:QRSize length:sizeof(QRSize)];
}

/**
*  设置二维码的纠错等级
*
*  @param level 48 <= level <= 51
*/
- (void)setQRCodeErrorCorrection:(NSInteger)level
{
Byte levelBytes [] = {0x1D,0x28,0x6B,0x03,0x00,0x31,0x45,level};
//    Byte levelBytes [] = {29,40,107,3,0,49,69,level};
[_printerData appendBytes:levelBytes length:sizeof(levelBytes)];
}

/**
*  将二维码数据存储到符号存储区
* [范围]:  4≤(pL+pH×256)≤7092 (0≤pL≤255,0≤pH≤27)
* cn=49
* fn=80
* m=48
* k=(pL+pH×256)-3, k就是数据的长度
*
*  @param info 二维码数据
*/
- (void)setQRCodeInfo:(NSString *)info
{
NSInteger kLength = info.length + 3;
NSInteger pL = kLength % 256;
NSInteger pH = kLength / 256;

Byte dataBytes [] = {0x1D,0x28,0x6B,pL,pH,0x31,0x50,48};
//    Byte dataBytes [] = {29,40,107,pL,pH,49,80,48};
[_printerData appendBytes:dataBytes length:sizeof(dataBytes)];
NSData *infoData = [info dataUsingEncoding:NSUTF8StringEncoding];
[_printerData appendData:infoData];
//    [self setText:info];
}

/**
*  打印之前存储的二维码信息
*/
- (void)printStoredQRData
{
Byte printBytes [] = {0x1D,0x28,0x6B,0x03,0x00,0x31,0x51,48};
//    Byte printBytes [] = {29,40,107,3,0,49,81,48};
[_printerData appendBytes:printBytes length:sizeof(printBytes)];
}

#pragma mark - ------------function method ----------------
#pragma mark  文字
- (void)appendText:(NSString *)text alignment:(HLTextAlignment)alignment
{
[self appendText:text alignment:alignment fontSize:HLFontSizeTitleSmalle];
}

- (void)appendText:(NSString *)text alignment:(HLTextAlignment)alignment fontSize:(HLFontSize)fontSize
{
// 1.文字对齐方式
[self setAlignment:alignment];
// 2.设置字号
[self setFontSize:fontSize];
// 3.设置标题内容
[self setText:text];
// 4.换行
[self appendNewLine];
if (fontSize != HLFontSizeTitleSmalle) {
    [self appendNewLine];
}
}

- (void)appendTitle:(NSString *)title value:(NSString *)value
{
[self appendTitle:title value:value fontSize:HLFontSizeTitleSmalle];
}

- (void)appendTitle:(NSString *)title value:(NSString *)value fontSize:(HLFontSize)fontSize
{
// 1.设置对齐方式
[self setAlignment:HLTextAlignmentLeft];
// 2.设置字号
[self setFontSize:fontSize];
// 3.设置标题内容
[self setText:title];
// 4.设置实际值
[self setOffsetText:value];
// 5.换行
[self appendNewLine];
if (fontSize != HLFontSizeTitleSmalle) {
    [self appendNewLine];
}
}

- (void)appendTitle:(NSString *)title value:(NSString *)value valueOffset:(NSInteger)offset
{
[self appendTitle:title value:value valueOffset:offset fontSize:HLFontSizeTitleSmalle];
}

- (void)appendTitle:(NSString *)title value:(NSString *)value valueOffset:(NSInteger)offset fontSize:(HLFontSize)fontSize
{
// 1.设置对齐方式
[self setAlignment:HLTextAlignmentLeft];
// 2.设置字号
[self setFontSize:fontSize];
// 3.设置标题内容
[self setText:title];
// 4.设置内容偏移量
[self setOffset:offset];
// 5.设置实际值
[self setText:value];
// 6.换行
[self appendNewLine];
if (fontSize != HLFontSizeTitleSmalle) {
    [self appendNewLine];
}
}

- (void)appendLeftText:(NSString *)left middleText:(NSString *)middle rightText:(NSString *)right isTitle:(BOOL)isTitle
{
[self setAlignment:HLTextAlignmentLeft];
[self setFontSize:HLFontSizeTitleSmalle];
NSInteger offset = 0;
if (!isTitle) {
    offset = 10;
}

if (left) {
    [self setText:left maxChar:10];
}

if (middle) {
    [self setOffset:150 + offset];
    [self setText:middle];
}

if (right) {
    [self setOffset:300 + offset];
    [self setText:right];
}

[self appendNewLine];

}

#pragma mark 图片
- (void)appendImage:(UIImage *)image alignment:(HLTextAlignment)alignment maxWidth:(CGFloat)maxWidth
{
if (!image) {
    return;
}

// 1.设置图片对齐方式
[self setAlignment:alignment];

// 2.设置图片
UIImage *newImage = [image imageWithscaleMaxWidth:maxWidth];

NSData *imageData = [newImage bitmapData];
[_printerData appendData:imageData];

// 3.换行
[self appendNewLine];

// 4.打印图片后,恢复文字的行间距
Byte lineSpace[] = {0x1B,0x32};
[_printerData appendBytes:lineSpace length:sizeof(lineSpace)];
}

- (void)appendBarCodeWithInfo:(NSString *)info
{
[self appendBarCodeWithInfo:info alignment:HLTextAlignmentCenter maxWidth:300];
}

- (void)appendBarCodeWithInfo:(NSString *)info alignment:(HLTextAlignment)alignment maxWidth:(CGFloat)maxWidth
{
UIImage *barImage = [UIImage barCodeImageWithInfo:info];
[self appendImage:barImage alignment:alignment maxWidth:maxWidth];
}

- (void)appendQRCodeWithInfo:(NSString *)info size:(NSInteger)size
{
[self appendQRCodeWithInfo:info size:size alignment:HLTextAlignmentCenter];
}

- (void)appendQRCodeWithInfo:(NSString *)info size:(NSInteger)size alignment:(HLTextAlignment)alignment
{
[self setAlignment:alignment];
[self setQRCodeSize:size];
[self setQRCodeErrorCorrection:48];
[self setQRCodeInfo:info];
[self printStoredQRData];
[self appendNewLine];
}

- (void)appendQRCodeWithInfo:(NSString *)info
{
[self appendQRCodeWithInfo:info centerImage:nil alignment:HLTextAlignmentCenter maxWidth:250];
}

- (void)appendQRCodeWithInfo:(NSString *)info centerImage:(UIImage *)centerImage alignment:(HLTextAlignment)alignment maxWidth:(CGFloat )maxWidth
{
UIImage *QRImage = [UIImage qrCodeImageWithInfo:info centerImage:centerImage width:maxWidth];
[self appendImage:QRImage alignment:alignment maxWidth:maxWidth];
}

#pragma mark 其他
- (void)appendSeperatorLine
{
// 1.设置分割线居中
[self setAlignment:HLTextAlignmentCenter];
// 2.设置字号
[self setFontSize:HLFontSizeTitleSmalle];
// 3.添加分割线
NSString *line = @"- - - - - - - - - - - - - - - -";
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [line dataUsingEncoding:enc];
[_printerData appendData:data];
// 4.换行
[self appendNewLine];
}

- (void)appendFooter:(NSString *)footerInfo
{
[self appendSeperatorLine];
if (!footerInfo) {
    footerInfo = @"谢谢惠顾,欢迎下次光临!";
}
[self appendText:footerInfo alignment:HLTextAlignmentCenter];
}

- (NSData *)getFinalData
{
return _printerData;
}

@end

控制器中使用方法如下:

#import "ViewController.h"
#import "JWBluetoothManage.h"

#define WeakSelf __block __weak typeof(self)weakSelf = self;
@interface ViewController () <UITableViewDataSource,UITableViewDelegate>{
    JWBluetoothManage * manage;
}
@property (nonatomic, strong) UITableView * tableView;
@property (nonatomic, strong) NSMutableArray * dataSource; //设备列表
@property (nonatomic, strong) NSMutableArray * rssisArray; //信号强度 可选择性使用

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"蓝牙列表";
    self.dataSource = @[].mutableCopy;
    self.rssisArray = @[].mutableCopy;
    [self _createTableView];
    manage = [JWBluetoothManage sharedInstance];
    WeakSelf
    [manage beginScanPerpheralSuccess:^(NSArray<CBPeripheral *> *peripherals, NSArray<NSNumber *> *rssis) {
        weakSelf.dataSource = [NSMutableArray arrayWithArray:peripherals];
        weakSelf.rssisArray = [NSMutableArray arrayWithArray:rssis];
        [weakSelf.tableView reloadData];
    } failure:^(CBManagerState status) {
        [ProgressShow alertView:self.view Message:[ProgressShow getBluetoothErrorInfo:status] cb:nil];
    }];
    manage.disConnectBlock = ^(CBPeripheral *perpheral, NSError *error) {
        NSLog(@"设备已经断开连接!");
        weakSelf.title = @"蓝牙列表";
    };
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"打印" style:UIBarButtonItemStylePlain target:self action:@selector(printe)];
    
    self.view.backgroundColor = [UIColor cyanColor];
}
- (void)printe{
    if (manage.stage != JWScanStageCharacteristics) {
        [ProgressShow alertView:self.view Message:@"打印机正在准备中..." cb:nil];
        return;
    }
    JWPrinter *printer = [[JWPrinter alloc] init];
    NSString *str1 = @"=============测试支付=============";
    [printer appendText:str1 alignment:HLTextAlignmentCenter];
    [printer appendTitle:@"商户名称:" value:@"这是测试啊啊啊啊啊啊"];
    [printer appendTitle:@"商户编号:" value:@"00000000000"];
    [printer appendTitle:@"订单编号:" value:@"LLLLLLLLLLL"];
    [printer appendTitle:@"交易类型:" value:@"这是测试的支付支付"];
    [printer appendTitle:@"交易时间:" value:@"2018-09-13"];
    [printer appendTitle:@"金    额:" value:@"10000000000000元"];
    [printer appendFooter:@"欢迎使用测试支付!"];
    [printer appendNewLine];
    NSData *mainData = [printer getFinalData];
    [[JWBluetoothManage sharedInstance] sendPrintData:mainData completion:^(BOOL completion, CBPeripheral *connectPerpheral,NSString *error) {
        if (completion) {
            NSLog(@"打印成功");
        }else{
            NSLog(@"写入错误---:%@",error);
        }
    }];
}
-(void)viewWillAppear:(BOOL)animated{
    WeakSelf
    [super viewWillAppear:animated];
    [manage autoConnectLastPeripheralCompletion:^(CBPeripheral *perpheral, NSError *error) {
        if (!error) {
            [ProgressShow alertView:self.view Message:@"连接成功!" cb:nil];
            weakSelf.title = [NSString stringWithFormat:@"已连接-%@",perpheral.name];
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf.tableView reloadData];
            });
        }else{
            [ProgressShow alertView:self.view Message:error.domain cb:nil];
        }
    }];
    
}
#pragma mark tableview medthod
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.dataSource.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *identifier = @"identifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    CBPeripheral *peripherral = [self.dataSource objectAtIndex:indexPath.row];
    if (peripherral.state == CBPeripheralStateConnected) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    cell.textLabel.text = [NSString stringWithFormat:@"名称:%@",peripherral.name];
    NSNumber * rssis = self.rssisArray[indexPath.row];
    cell.detailTextLabel.text = [NSString stringWithFormat:@"强度:%@",rssis];
    
    return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    CBPeripheral *peripheral = [self.dataSource objectAtIndex:indexPath.row];
    [manage connectPeripheral:peripheral completion:^(CBPeripheral *perpheral, NSError *error) {
        if (!error) {
            [ProgressShow alertView:self.view Message:@"连接成功!" cb:nil];
            self.title = [NSString stringWithFormat:@"已连接-%@",perpheral.name];
            dispatch_async(dispatch_get_main_queue(), ^{
                [tableView reloadData];
            });
        }else{
            [ProgressShow alertView:self.view Message:error.domain cb:nil];
        }
    }];
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}


- (void) _createTableView{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 64) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        _tableView.tableFooterView = [UIView new];
        if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
            [_tableView setSeparatorInset:UIEdgeInsetsZero];
        }
        if ([_tableView respondsToSelector:@selector(setLayoutMargins:)]) {
            [_tableView setLayoutMargins:UIEdgeInsetsZero];
        }
    }
    if (![self.view.subviews containsObject:_tableView]) {
        [self.view addSubview:_tableView];
    }else{
        [_tableView reloadData];
    }
}




@end

相关文章

  • 打印机

    iOS开发之蓝牙/Socket链接小票打印机(一)iOS开发之蓝牙/Socket链接小票打印机(二) iOS so...

  • iOS 打印小票

    接下来是.m文件。 控制文字对齐方式,字号,信息等。 JWPrinter.m文件如下: 控制器中使用方法如下:

  • iOS 蓝牙打印小票

    前言: 最近做了款蓝牙打印的功能,包含蓝牙自动连接,蓝牙搜索,连接之后进行打印。总结了下知识点,写了一个简单的De...

  • iOS蓝牙打印小票

    最近搞了个蓝牙打印小票的小东西,先上效果 数据格式 json: 使用: 话不多说上Demo:GitHub地址

  • iOS 打印机打印小票

    关于移动端控制打印机打印,虽然网上有一些教程,但是总是那样的不尽人意。摸索了一段时间总算有些成果,来和大家分享下!...

  • iOS CoreBluetooth 的使用讲解

    最近研究了iOS下连接蓝牙打印机,实现打印购物小票的功能,对iOS中BLE 4.0的使用有了一定的了解,这里记录一...

  • iOS开发 蓝牙打印小票

    要求:手机通过蓝牙连接蓝牙打印机,在手机上点击‘打印’,打印机就打印出小票(小票就跟送外卖的那种)。 设备:BT5...

  • iOS Bluetooth 打印小票(二)

    在上一篇中介绍了打印小票所需要的命令,这一篇介绍Bluetooth连接蓝牙和打印小票的全过程。 CoreBluet...

  • iOS Bluetooth 打印小票(一)

    在iOS app中连接蓝牙打印机打印商品小票,在没有电脑只有手机的情况下,感觉非常实用,而且最近经常最近公司正好也...

  • pyqt5-商店小票打印的实现模板

    说明 最近在用pyqt5做商店小票打印,用的是得力DL-581PW(NEW)热敏小票打印机。 商店小票打印,属于e...

网友评论

    本文标题:iOS 打印小票

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