Skip to content

Instantly share code, notes, and snippets.

@jeffleeismyhero
Created October 20, 2015 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffleeismyhero/8b3486f37d4ed7b0a60c to your computer and use it in GitHub Desktop.
Save jeffleeismyhero/8b3486f37d4ed7b0a60c to your computer and use it in GitHub Desktop.
Zebra ZQ510 Print Job
#import "VPDeviceDelegate.h"
#import "AFNetworking.h"
#import "VPConstants.h"
// Zebra Printers
#import "ZebraPrinter.h"
#import "ZebraPrinterFactory.h"
#import "ZebraPrinterConnection.h"
#import "MfiBtPrinterConnection.h"
#import "PrinterStatus.h"
#import "SGD.h"
#import <ExternalAccessory/ExternalAccessory.h>
#import "AppDelegate.h"
#define VP_APPDELEGATE ((AppDelegate *)[UIApplication sharedApplication].delegate)
@implementation VPDevices
@synthesize delegate;
- (id)init {
self = [super init];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(accessoryDidConnect:)
name:EAAccessoryDidConnectNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(accessoryDidDisconnect:)
name:EAAccessoryDidDisconnectNotification
object:nil];
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications]; //we want to hear about accessories connecting and disconnecting
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidDisconnectNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidConnectNotification object:nil];
[[EAAccessoryManager sharedAccessoryManager] unregisterForLocalNotifications];
}
- (void)deviceSelection {
EAAccessoryManager *accessoryManager = [EAAccessoryManager sharedAccessoryManager];
NSLog(@"Connected: %@", [accessoryManager connectedAccessories]);
[accessoryManager showBluetoothAccessoryPickerWithNameFilter:nil completion:^(NSError * _Nullable error) {
NSLog(@"Finished selection of accessory.");
}];
}
#pragma mark - Printer
// Determines which type(s) of printer is connected
- (NSString *)connectedPrinterType {
NSString *printerType = @"";
if ([self zebraPrinterStatus]) {
printerType = [NSString stringWithFormat:@"%@%@", printerType, @"[ZEBRA]"];
}
return printerType;
}
/*
// The methods that generate this data should be pulled out into another class
*/
- (BOOL)printReceipt:(Order *)order {
NSLog(@"Printing receipt...");
NSError *error = nil;
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) {
__block BOOL status = NO;
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
// Dispatch this task to the default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
if (status) {
NSError *error = nil;
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error];
NSLog(@"ZEBRA: Language error: %@", error);
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error];
NSLog(@"ZEBRA: Connection error: %@", error);
// Store the logo image on the printer
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"];
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil];
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error];
NSLog(@"ZEBRA: Graphics error: %@", error);
// Spacing and length
int leftSpacing;
long length = 0;
NSString *padding;
// Start of print
NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0";
// Start off with 10 dots of padding
length += 10;
NSString *imageName = @"LOGO_V5";
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, imageName];
length += 150;
// Receipt Header
NSString *header = @"RECEIPT ONLY";
leftSpacing = ceil((18 - [header length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
header = [padding stringByAppendingString:header];
printString = [NSString stringWithFormat:@"%@^A2,N,24,24^FO30,%ld^FD%@^FS", printString, length, header];
// This portion is approximately 60 dots
length += 60;
// Terminal and Date line
// Terminal Number
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]];
// Order Date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"];
NSString *dateString = [dateFormatter stringFromDate:order.completedAt];
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString];
printString = [printString stringByAppendingString:terminalString];
// This portion is approximately 25 dots
length += 25;
// Order Number line
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber];
printString = [printString stringByAppendingString:orderNumberString];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
// Line Items
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems];
for (id lineItem in lineItems) {
NSDictionary *line = [lineItem objectForKey:@"line_item"];
NSString *ticketLabel = [line objectForKey:@"ticket_label"];
NSString *quantity = [[line objectForKey:@"quantity"] stringValue];
NSString *price = [line objectForKey:@"price"];
NSString *unadjustedLineTotal = [line objectForKey:@"unadjusted_line_total"];
NSString *product = [NSString stringWithFormat:@"%@ (%@ @ %@)", ticketLabel, quantity, price];
product = [product stringByPaddingToLength:(45 - [unadjustedLineTotal length]) withString:@" " startingAtIndex:0];
// Order Line Items
NSString *lineItemString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, product, unadjustedLineTotal];
printString = [printString stringByAppendingString:lineItemString];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
// Order Discounts
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments];
NSArray *discounts = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"];
}]];
NSArray *comps = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"];
}]];
NSArray *wholesalers = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"];
}]];
NSArray *concierges = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"];
}]];
if ([discounts count] > 0) {
// Add 25 dots of padding (about 1 line)
length += 25;
NSString *discountTotal = [@"Discount Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
// Discount Total
NSString *discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString];
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect
// This portion is approximately 25 dots
length += 25;
for (id discount in discounts) {
id discountObject = [discount objectForKey:@"adjustment"];
NSDictionary *discountLabel = [discountObject objectForKey:@"label"];
NSString *discountQuantity = [discountObject objectForKey:@"quantity"];
NSString *discountUnitAmount = [discountObject objectForKey:@"formatted_unit_amount"];
NSString *discountAmount = [discountObject objectForKey:@"formatted_total_amount"];
NSString *discountString = [NSString stringWithFormat:@" %@ (%@ @ %@)", discountLabel, discountQuantity, discountUnitAmount];
discountString = [discountString stringByPaddingToLength:(45 - [discountAmount length]) withString:@" " startingAtIndex:0];
NSString *discountLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountString, discountAmount];
printString = [printString stringByAppendingString:discountLine];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
} else if ([comps count] > 0) {
NSString *compTotal = [@"Comp Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
// This portion is approximately 25 dots
length += 25;
} else if ([wholesalers count] > 0) {
NSString *wholesaleTotal = [@"Wholesale Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *wholesaleLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, wholesaleTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:wholesaleLine];
// This portion is approximately 25 dots
length += 25;
} else if ([concierges count] > 0) {
NSString *conciergeTotal = [@"Concierge Deposit:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
// Total Line
NSString *total = [@"TOTAL" stringByPaddingToLength:(45 - [order.orderTotal length]) withString:@" " startingAtIndex:0];
NSString *totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
// Payment Detail
NSArray *transactions = [NSKeyedUnarchiver unarchiveObjectWithData:order.transactions];
for (id transaction in transactions) {
NSDictionary *payment = [transaction objectForKey:@"transaction"];
NSString *gatewayTransactionID = [payment objectForKey:@"gateway_transaction_id"];
NSString *cardType = [payment objectForKey:@"card_type"];
NSString *cardNumber = [payment objectForKey:@"last_digits"];
NSString *cardTypeString = [[cardType uppercaseString] stringByPaddingToLength:(45 - [order.amountTendered length]) withString:@" " startingAtIndex:0];
NSString *cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardTypeString, order.amountTendered];
printString = [printString stringByAppendingString:cardTypeLine];
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, cardTypeString, order.amountTendered];
printString = [printString stringByAppendingString:cardTypeLine];
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, cardTypeString, order.amountTendered];
printString = [printString stringByAppendingString:cardTypeLine];
// This portion is approximately 25 dots
length += 25;
if ([cardNumber length] > 0) {
NSString *cardNumberString = [@" Card Number (last 4):" stringByPaddingToLength:(45 - [cardNumber length]) withString:@" " startingAtIndex:0];
NSString *cardNumberLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardNumberString, cardNumber];
printString = [printString stringByAppendingString:cardNumberLine];
// This portion is approximately 25 dots
length += 25;
}
NSString *responseCodeString = [@" Transaction ID:" stringByPaddingToLength:(45 - [gatewayTransactionID length]) withString:@" " startingAtIndex:0];
NSString *responseCodeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, responseCodeString, gatewayTransactionID];
printString = [printString stringByAppendingString:responseCodeLine];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
NSString *change = [@"CHANGE:" stringByPaddingToLength:(45 - [order.changeDue length]) withString:@" " startingAtIndex:0];
NSString *changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, change, order.changeDue];
printString = [printString stringByAppendingString:changeLine];
changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, change, order.changeDue];
printString = [printString stringByAppendingString:changeLine];
changeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, change, order.changeDue];
printString = [printString stringByAppendingString:changeLine];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
// Transfer/Refund Policy and Footer
NSString *transferPolicy = @"All sales are final. Non-transferable.";
leftSpacing = ceil((45 - [transferPolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
transferPolicy = [padding stringByAppendingString:transferPolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, transferPolicy];
// This portion is approximately 25 dots
length += 25;
NSString *refundPolicy = @"No refunds. No exchanges.";
leftSpacing = ceil((45 - [refundPolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
refundPolicy = [padding stringByAppendingString:refundPolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy];
// This portion is approximately 25 dots
length += 25;
NSString *thankYouMessage = @"THANK YOU!";
leftSpacing = ceil((45 - [thankYouMessage length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
thankYouMessage = [padding stringByAppendingString:thankYouMessage];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage];
// End of print
printString = [printString stringByAppendingString:@"^XZ"];
// Feed the paper for tearing
length += 100;
printString = [NSString stringWithFormat:printString, length];
NSLog(@"[PRINT STRING]: %@", printString);
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding];
[weakSelf printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]];
}
[connection close];
});
}
return YES;
}
- (BOOL)printRefundReceipt:(Order *)order {
NSLog(@"Printing refund receipt...");
NSError *error = nil;
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) {
__block BOOL status = NO;
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
// Dispatch this task to the default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
if (status) {
NSError *error = nil;
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error];
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error];
// Store the logo image on the printer
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"];
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil];
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error];
// Spacing and length
int leftSpacing;
__block long length = 0;
NSString *padding;
// Start of print
__block NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0";
// Start off with 10 dots of padding
length += 10;
NSString *imageName = @"LOGO_V5";
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, imageName];
length += 150;
// Receipt Header
NSString *header = @"RECEIPT ONLY";
leftSpacing = ceil((18 - [header length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
header = [padding stringByAppendingString:header];
printString = [NSString stringWithFormat:@"%@^A2,N,24,24^FO30,%ld^FD%@^FS", printString, length, header];
// This portion is approximately 60 dots
length += 60;
// Terminal and Date line
// Terminal Number
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]];
// Order Date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"];
NSString *dateString = [dateFormatter stringFromDate:order.completedAt];
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString];
printString = [printString stringByAppendingString:terminalString];
// This portion is approximately 25 dots
length += 25;
// Order Number line
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber];
printString = [printString stringByAppendingString:orderNumberString];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
// Line Items
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems];
for (id lineItem in lineItems) {
NSDictionary *line = [lineItem objectForKey:@"line_item"];
NSString *ticketLabel = [line objectForKey:@"ticket_label"];
NSString *quantity = [[line objectForKey:@"quantity"] stringValue];
NSString *price = [line objectForKey:@"price"];
NSString *unadjustedLineTotal = [line objectForKey:@"unadjusted_line_total"];
NSString *product = [NSString stringWithFormat:@"%@ (%@ @ %@)", ticketLabel, quantity, price];
product = [product stringByPaddingToLength:(45 - [unadjustedLineTotal length]) withString:@" " startingAtIndex:0];
// Order Line Items
NSString *lineItemString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, product, unadjustedLineTotal];
printString = [printString stringByAppendingString:lineItemString];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
// Order Discounts
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments];
NSArray *discounts = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"];
}]];
NSArray *comps = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"];
}]];
NSArray *wholesalers = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"];
}]];
NSArray *concierges = [adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"];
}]];
if ([discounts count] > 0) {
// Add 25 dots of padding (about 1 line)
length += 25;
NSString *discountTotal = [@"Discount Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
// Discount Total
NSString *discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString];
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect
discountTotalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, discountTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:discountTotalString]; // Creates a bold effect
// This portion is approximately 25 dots
length += 25;
for (id discount in discounts) {
id discountObject = [discount objectForKey:@"adjustment"];
NSDictionary *discountLabel = [discountObject objectForKey:@"label"];
NSString *discountQuantity = [discountObject objectForKey:@"quantity"];
NSString *discountUnitAmount = [discountObject objectForKey:@"formatted_unit_amount"];
NSString *discountAmount = [discountObject objectForKey:@"formatted_total_amount"];
NSString *discountString = [NSString stringWithFormat:@" %@ (%@ @ %@)", discountLabel, discountQuantity, discountUnitAmount];
discountString = [discountString stringByPaddingToLength:(45 - [discountAmount length]) withString:@" " startingAtIndex:0];
NSString *discountLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, discountString, discountAmount];
printString = [printString stringByAppendingString:discountLine];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
} else if ([comps count] > 0) {
NSString *compTotal = [@"Comp Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
compLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, compTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:compLine];
// This portion is approximately 25 dots
length += 25;
} else if ([wholesalers count] > 0) {
NSString *wholesaleTotal = [@"Wholesale Total:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *wholesaleLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, wholesaleTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:wholesaleLine];
// This portion is approximately 25 dots
length += 25;
} else if ([concierges count] > 0) {
NSString *conciergeTotal = [@"Concierge Deposit:" stringByPaddingToLength:(45 - [order.adjustmentTotal length]) withString:@" " startingAtIndex:0];
NSString *conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
conciergeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, conciergeTotal, order.adjustmentTotal];
printString = [printString stringByAppendingString:conciergeLine];
// This portion is approximately 25 dots
length += 25;
}
// Add 25 dots of padding (about 1 line)
length += 25;
// Total Line
NSString *total = [@"TOTAL" stringByPaddingToLength:(45 - [order.orderTotal length]) withString:@" " startingAtIndex:0];
NSString *totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
totalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, total, order.orderTotal];
printString = [printString stringByAppendingString:totalLine];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
NSString *refundTotal = [@"REFUND TOTAL:" stringByPaddingToLength:(45 - [order.refundTotal length]) withString:@" " startingAtIndex:0];
NSString *refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, refundTotal, order.refundTotal];
printString = [printString stringByAppendingString:refundTotalLine];
refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, refundTotal, order.refundTotal];
printString = [printString stringByAppendingString:refundTotalLine];
refundTotalLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, refundTotal, order.refundTotal];
printString = [printString stringByAppendingString:refundTotalLine];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
// Refund Detail
NSArray *refunds = [NSKeyedUnarchiver unarchiveObjectWithData:order.refunds];
[refunds enumerateObjectsUsingBlock:^(id transaction, NSUInteger idx, BOOL *stop) {
NSDictionary *refund = [transaction objectForKey:@"refund"];
NSString *gatewayTransactionID = [refund objectForKey:@"gateway_transaction_id"];
NSString *cardType = [refund objectForKey:@"card_type"];
NSString *cardNumber = [refund objectForKey:@"last_digits"];
NSString *refundAmount = [refund objectForKey:@"amount"];
refundAmount = [@"-" stringByAppendingString:refundAmount];
NSString *cardTypeString = [[cardType uppercaseString] stringByPaddingToLength:(45 - [refundAmount length]) withString:@" " startingAtIndex:0];
NSString *cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardTypeString, refundAmount];
printString = [printString stringByAppendingString:cardTypeLine];
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO19,%ld^FD%@%@^FS", length, cardTypeString, refundAmount];
printString = [printString stringByAppendingString:cardTypeLine];
cardTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length+1, cardTypeString, refundAmount];
printString = [printString stringByAppendingString:cardTypeLine];
// This portion is approximately 25 dots
length += 25;
if ([cardNumber length] > 0) {
NSString *cardNumberString = [@" Card Number (last 4):" stringByPaddingToLength:(45 - [cardNumber length]) withString:@" " startingAtIndex:0];
NSString *cardNumberLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, cardNumberString, cardNumber];
printString = [printString stringByAppendingString:cardNumberLine];
// This portion is approximately 25 dots
length += 25;
}
NSString *responseCodeString = [@" Transaction ID:" stringByPaddingToLength:(45 - [gatewayTransactionID length]) withString:@" " startingAtIndex:0];
NSString *responseCodeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, responseCodeString, gatewayTransactionID];
printString = [printString stringByAppendingString:responseCodeLine];
// This portion is approximately 25 dots
length += 25;
}];
// Add 25 dots of padding (about 1 line)
length += 25;
// Transfer/Refund Policy and Footer
NSString *transferPolicy = @"All sales are final. Non-transferable.";
leftSpacing = ceil((45 - [transferPolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
transferPolicy = [padding stringByAppendingString:transferPolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, transferPolicy];
// This portion is approximately 25 dots
length += 25;
NSString *refundPolicy = @"No refunds. No exchanges.";
leftSpacing = ceil((45 - [refundPolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
refundPolicy = [padding stringByAppendingString:refundPolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy];
// This portion is approximately 25 dots
length += 25;
NSString *thankYouMessage = @"THANK YOU!";
leftSpacing = ceil((45 - [thankYouMessage length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
thankYouMessage = [padding stringByAppendingString:thankYouMessage];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage];
// End of print
printString = [printString stringByAppendingString:@"^XZ"];
// Feed the paper for tearing
length += 100;
printString = [NSString stringWithFormat:printString, length];
NSLog(@"[PRINT STRING]: %@", printString);
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding];
[self printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]];
}
[connection close];
});
}
return YES;
}
- (BOOL)printTickets:(Order *)order {
NSError *error = nil;
if ([[self connectedPrinterType] isEqualToString:@"[ZEBRA]"]) {
__block BOOL status = NO;
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
// Dispatch this task to the default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
if (status) {
NSError *error = nil;
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error];
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error];
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil];
UIImage *image;
// Store the logo image on the printer
image = [UIImage imageNamed:@"logo-v5.png"];
[graphicsUtil storeImage:@"LOGO_V5" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Store the HOHO image on the printer
image = [UIImage imageNamed:@"hop-on-hop-off-tour-logo-v4.png"];
[graphicsUtil storeImage:@"HOHO_V4" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Store the BSS image on the printer
image = [UIImage imageNamed:@"bss-train-logo-v2.png"];
[graphicsUtil storeImage:@"BSS_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Store the Cemetery image on the printer
image = [UIImage imageNamed:@"cemetery-tour-logo-v3.png"];
[graphicsUtil storeImage:@"CEMETERY_V3" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Store the Garden Tour image on the printer
image = [UIImage imageNamed:@"garden-tour-logo-v2.png"];
[graphicsUtil storeImage:@"GARDEN_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Store the FQ Tour image on the printer
image = [UIImage imageNamed:@"french-quarter-tour-logo-v2.png"];
[graphicsUtil storeImage:@"FQ_TOUR_V2" withImage:[image CGImage] withWidth:image.size.width andWithHeight:image.size.height error:&error];
// Spacing and length
NSString *padding;
int leftSpacing;
__block long length = 0;
// Start of print
__block NSString *printString = @"^XA^POI^PW576^MNN^LL%d^LH0,0";
// Start off with 10 dots of padding
length += 10;
NSArray *lineItems = [NSKeyedUnarchiver unarchiveObjectWithData:order.lineItems];
NSArray *adjustments = [NSKeyedUnarchiver unarchiveObjectWithData:order.adjustments];
NSMutableArray *discounts = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Discount"];
}]] mutableCopy];
NSMutableArray *comps = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Comp"];
}]] mutableCopy];
NSMutableArray *wholesalers = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Wholesaler"];
}]] mutableCopy];
NSMutableArray *concierges = [[adjustments filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [[[object objectForKey:@"adjustment"] objectForKey:@"adjustment_class"] isEqualToString:@"Concierge"];
}]] mutableCopy];
NSUInteger lineItemIndex = 0;
for (id lineItem in lineItems) {
NSDictionary *line = [lineItem objectForKey:@"line_item"];
NSString *ticketLabel = [line objectForKey:@"ticket_label"];
NSString *quantity = [[line objectForKey:@"quantity"] stringValue];
for (int i = 0; i < [quantity integerValue]; i++) {
// Ticket Header
if ([ticketLabel containsString:@"FQ Tour"]) {
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"];
length += 150;
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"FQ_TOUR_V2"];
length += 150;
} else if ([ticketLabel containsString:@"Garden Tour"]) {
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"];
length += 150;
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"GARDEN_V2"];
length += 150;
} else if ([ticketLabel containsString:@"Cemetery Tour"]) {
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"BSS_V2"];
length += 150;
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"CEMETERY_V3"];
length += 150;
} else {
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"LOGO_V5"];
length += 150;
printString = [NSString stringWithFormat:@"%@^FO50,%ld^XGE:%@.GRF,1,1^FS", printString, length, @"HOHO_V4"];
length += 150;
}
NSString *validRangeString = [line objectForKey:@"formatted_valid_range"];
NSArray *rangeStringArray = [validRangeString componentsSeparatedByString: @"\n"];
for (NSString *rangeString in rangeStringArray) {
leftSpacing = ceil((24 - [rangeString length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
NSString *rangeLine = [padding stringByAppendingString:rangeString];
printString = [NSString stringWithFormat:@"%@^A2,N,22^FO20,%ld^FD%@^FS", printString, length, rangeLine];
// This portion is approximately 40 dots
length += 40;
}
// Add 25 dots of padding (about 1 line)
length += 25;
NSString *cleanLabel = [ticketLabel stringByReplacingOccurrencesOfString:@"Audubon " withString:@""];
cleanLabel = [NSString stringWithFormat:@"1 %@", cleanLabel];
leftSpacing = ceil((23 - [cleanLabel length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
cleanLabel = [padding stringByAppendingString:cleanLabel];
printString = [NSString stringWithFormat:@"%@^A2,N,22^FO20,%ld^FD%@^FS", printString, length, cleanLabel];
// This portion is approximately 40 dots
length += 40;
// Add 25 dots of padding (about 1 line)
length += 25;
// Barcode (PDF 417)
printString = [NSString stringWithFormat:@"%@^FO100,%ld^B7N,8,5,7,14,N^FD%@^FS", printString, length, order.orderNumber];
// Barcode is approximately 140 dots
length += 140;
if ([discounts count] > 0) {
NSMutableDictionary *adjustment = [[discounts lastObject] mutableCopy];
NSUInteger adjustmentIndex = [discounts indexOfObject:adjustment];
NSMutableDictionary *discount = [[adjustment objectForKey:@"adjustment"] mutableCopy];
NSString *discountLabel = [discount objectForKey:@"label"];
NSNumber *discountQuantity = [discount objectForKey:@"quantity"];
NSString *discountString = [NSString stringWithFormat:@"%@ %@", discountLabel, @"Discount"];
if ([discountQuantity intValue] > 1) {
// Update the Discount Quantity
discountQuantity = [NSNumber numberWithInt:([discountQuantity intValue] - 1)];
[discount setValue:discountQuantity forKey:@"quantity"];
// Replace the Discount object in "discounts" array
[discounts replaceObjectAtIndex:adjustmentIndex withObject:@{@"adjustment":discount}];
} else {
[discounts removeLastObject];
}
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [discountString length]) withString:@" " startingAtIndex:0];
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, discountString];
printString = [printString stringByAppendingString:saleTypeLine];
// This portion is approximately 25 dots
length += 25;
}
if ([comps count] > 0) {
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Complimentary" length]) withString:@" " startingAtIndex:0];
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Complimentary"];
printString = [printString stringByAppendingString:saleTypeLine];
// This portion is approximately 25 dots
length += 25;
} else if ([wholesalers count] > 0) {
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Wholesale" length]) withString:@" " startingAtIndex:0];
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Wholesale"];
printString = [printString stringByAppendingString:saleTypeLine];
// This portion is approximately 25 dots
length += 25;
} else if ([concierges count] > 0) {
NSString *saleTypeString = [@"Sale Type:" stringByPaddingToLength:(45 - [@"Concierge" length]) withString:@" " startingAtIndex:0];
NSString *saleTypeLine = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@%@^FS", length, saleTypeString, @"Concierge"];
printString = [printString stringByAppendingString:saleTypeLine];
// This portion is approximately 25 dots
length += 25;
}
// Ticket Purchase Details
// Terminal and Date line
// Terminal Number
NSString *terminalNumber = [NSString stringWithFormat:@"TERMINAL %03d", [[order valueForKey:@"deviceID"] intValue]];
// Order Date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"];
NSString *dateString = [dateFormatter stringFromDate:order.completedAt];
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FD%@ %@^FS", length, terminalNumber, dateString];
printString = [printString stringByAppendingString:terminalString];
// This portion is approximately 25 dots
length += 25;
// Order Number line
NSString *orderNumberString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,%ld^FDOrder Number: %@^FS", length, order.orderNumber];
printString = [printString stringByAppendingString:orderNumberString];
// This portion is approximately 25 dots
length += 25;
// Add 25 dots of padding (about 1 line)
length += 25;
// Print Ticket Footer
if ([ticketLabel containsString:@"Cemetery Tour"]) {
NSString *policy = @"Tour Times: 9:30 10:30 11:30 12:30 1:30";
leftSpacing = ceil((45 - [policy length]) / 2);
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Present Ticket to Guide at Basin St. Station";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"First Come-First Serve; Limited to 28 guests.";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Uneven Surfaces Everywhere - Watch your Step!";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
} else if ([ticketLabel containsString:@"Tour"]) {
NSString *policy = @"Uneven Surfaces Everywhere - Watch your Step!";
leftSpacing = ceil((45 - [policy length]) / 2);
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Please give this ticket to Tour Host at";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"start of tour.";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Space is Limited: 28 Guests per tour,";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"First come First serve.";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
} else {
NSString *padding;
NSString *policy = @"Present Ticket to Bus Operator.";
int leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO19,%ld^FD%@^FS", printString, length, policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length+1, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"All Passengers must remain seated when";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"vehicle is in motion. No standing room.";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Smoking, Eating, Drinking Alcoholic Beverages";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"is prohibited on vehicles.";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
policy = @"Route, Stops and Timing are subject to change";
leftSpacing = ceil((45 - [policy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
policy = [padding stringByAppendingString:policy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, policy];
// This portion is approximately 25 dots
length += 25;
NSString *finalSalePolicy = @"All sales are final. Non-transferable.";
leftSpacing = ceil((45 - [finalSalePolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
finalSalePolicy = [padding stringByAppendingString:finalSalePolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, finalSalePolicy];
// This portion is approximately 25 dots
length += 25;
NSString *refundPolicy = @"No refunds. No exchanges.";
leftSpacing = ceil((45 - [refundPolicy length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
refundPolicy = [padding stringByAppendingString:refundPolicy];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, refundPolicy];
// This portion is approximately 25 dots
length += 25;
}
NSString *thankYouMessage = @"THANK YOU!";
leftSpacing = ceil((45 - [thankYouMessage length]) / 2);
padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
thankYouMessage = [padding stringByAppendingString:thankYouMessage];
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, thankYouMessage];
// Feed the paper for tearing
length += 100;
// Print cut lines
printString = [NSString stringWithFormat:@"%@^A2,N,12,12^FO20,%ld^FD%@^FS", printString, length, @" ----------------------------------------------"];
// Feed the paper for tearing
length += 100;
}
lineItemIndex++;
}
// End of print
printString = [printString stringByAppendingString:@"^XZ"];
printString = [NSString stringWithFormat:printString, length];
NSLog(@"[PRINT STRING]: %@", printString);
NSData *commands = [printString dataUsingEncoding:NSASCIIStringEncoding];
[self printReceiptAsOneJobUsingNSData:connection withData:[commands mutableCopy]];
}
[connection close];
[self printReceipt:order];
});
// Increment Print Counter
[self incrementPrintCounter:order];
}
return YES;
}
#pragma mark - Zebra Printer
- (BOOL)zebraPrinterStatus {
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
__block BOOL status = NO;
if ([serialNumber length] == 0) {
NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
NSString *zebraProtocol = @"com.zebra.rawport";
for (EAAccessory *accessory in accessories) {
if ([[accessory protocolStrings] containsObject:zebraProtocol]) {
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSLog(@"Setting zebraSerialNumber to %@", accessory.serialNumber);
serialNumber = accessory.serialNumber;
[preferences setObject:accessory.serialNumber forKey:@"zebraSerialNumber"];
[preferences synchronize];
break;
}
}
}
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
[connection close];
return status;
}
- (void)disableSleepMode {
__block BOOL status = NO;
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
if ([self zebraPrinterStatus]) {
//Dispatch this task to the default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
if (status) {
NSError *error = nil;
[SGD SET:@"power.sleep.enable" withValue:@"off" andWithPrinterConnection:connection error:&error];
}
[connection close];
});
}
}
- (void)printZebraSelfTest {
__block BOOL status = NO;
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *serialNumber = [preferences objectForKey:@"zebraSerialNumber"];
// [self disableSleepMode];
// Dispatch this task to the default queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// Instantiate connection to Zebra Bluetooth accessory
id <ZebraPrinterConnection, NSObject> connection = [[MfiBtPrinterConnection alloc] initWithSerialNumber:serialNumber];
// Open the connection - physical connection is established here.
[connection open];
status = [connection isConnected];
if (status) {
NSError *error = nil;
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error];
// [[printer getToolsUtil] reset:&error];
[SGD SET:@"device.languages" withValue:@"zpl" andWithPrinterConnection:connection error:&error];
// [SGD SET:@"power.sleep.enable" withValue:@"off" andWithPrinterConnection:connection error:&error];
// [SGD SET:@"device.languages" withValue:@"line_print" andWithPrinterConnection:connection error:&error];
NSString *sampleZplReceipt = [self createZplReceipt];
NSData *sampleZplReceiptAsNsData = [sampleZplReceipt dataUsingEncoding:NSASCIIStringEncoding];
// Store the logo image on the printer
UIImage *logoImage = [UIImage imageNamed:@"logo-v5.png"];
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil];
[graphicsUtil storeImage:@"LOGO_V5" withImage:[logoImage CGImage] withWidth:logoImage.size.width andWithHeight:logoImage.size.height error:&error];
[self printReceiptAsOneJobUsingNSData:connection withData:[sampleZplReceiptAsNsData mutableCopy]];
}
[connection close];
});
}
- (void)printReceiptAsOneJobUsingNSData:(id<NSObject,ZebraPrinterConnection>)connection withData:(NSMutableData*)commands {
/*
Sending large amounts of data in a single write command can overflow the NSStream buffers which are the underlying mechanism used by the SDK to communicate with the printers.
This method breaks up large data into smaller chunks to send to the printer
*/
NSError *error = nil;
[connection open];
[connection write:commands error:&error];
NSLog(@"ERROR: %@", error);
// long blockSize = 1024;
// long totalSize = commands.length;
// long bytesRemaining = totalSize;
//
// while (bytesRemaining > 0) {
// long bytesToSend = MIN(blockSize, bytesRemaining);
// NSRange range = NSMakeRange(0, bytesToSend);
//
// NSData *partialChunk = [commands subdataWithRange:range];
// [connection write:partialChunk error:&error];
// NSLog(@"ERROR: %@", error);
// bytesRemaining -= bytesToSend;
//
// [commands replaceBytesInRange:range withBytes:NULL length:0];
// }
}
- (NSString*)createZplReceipt {
NSString *printData =
@"^XA^POI^PW576^MNN^LL%ld^LH0,0" \
@"^FO50,0^XGE:LOGO_V5.GRF,1,1^FS" \
@"^A1,N,24,24" \
@"^FO30,140^FDTEST RECEIPT ONLY^FS" \
// Terminal and Date
@"%@" \
// Order Number
@"%@" \
@"^FO0,250" \
@"^A2,N,12,12" \
@"^FD ----------------------------------------------^FS" \
// Barcode (PDF 417)
@"^FO100,280" \
@"^B7N,8,5,7,14,N^FDCSS-000-YYMMDDHHMMSSSSS^FS" \
@"^FO20,410" \
@"^A2,N,12,12" \
@"^FD%@^FS" \
@"^XZ";
long length = 500;
NSString *footer = @"No Refunds or Exchanges!";
int leftSpacing = ceil((45 - [footer length]) / 2);
NSString *padding = [@"" stringByPaddingToLength:leftSpacing withString:@" " startingAtIndex:0];
footer = [padding stringByAppendingString:footer];
// Terminal and Date line
// Order Date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
[dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss a"];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSString *terminalString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,200^FD%@ %@^FS", @"TERMINAL 001", dateString];
// Order Number line
NSString *orderString = [NSString stringWithFormat:@"^A2,N,12,12^FO20,225^FDOrder Number: %@^FS", @"CSS-000-YYMMDDHHMMSSSSS"];
// Combine it all
NSString *printString = [NSString stringWithFormat:printData, length, terminalString, orderString, footer];
return printString;
}
#pragma mark - Accessories
- (void)accessoryDidConnect:(NSNotification *)notification {
EAAccessory *accessory = [[notification userInfo] objectForKey:EAAccessoryKey];
NSLog(@"[VP]: Accessory %@ has connected", accessory.serialNumber);
NSString *zebraProtocol = @"com.zebra.rawport";
if ([accessory.protocolStrings containsObject:zebraProtocol]) {
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSLog(@"Setting zebraSerialNumber to %@", accessory.serialNumber);
[preferences setObject:accessory.serialNumber forKey:@"zebraSerialNumber"];
[preferences synchronize];
}
}
- (void)accessoryDidDisconnect:(NSNotification *)notification {
EAAccessory *accessory = [[notification userInfo] objectForKey:EAAccessoryKey];
NSLog(@"[VP]: Accessory %@ has disconnected", accessory.serialNumber);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment