Innovaptor Logo

Get started with Bluetooth Printing on iOS with the Bixolon iOS SDK

We recently had to implement bluetooth printing to a mobile label printer to one of our applications. The specific printer was a Bixolon SPP-R200IIIik. Bixolon provides documentation and and SDK on their homepage.

Unfortunately, the documentation is (in my humble opinion) pretty bad and was not helpful at all in implementing this feature. The accompanying sample project is very convoluted, but at last I was able to finally print something after probing the sample project for some hours.

Since I had such a hard time getting started, I decided to write this (very minimalistic) guide to help you get started.

Setup

Download the SDK from bixolon and add the lib folder to your Xcode project. Make sure that libBixolonUPOS.a is linked in “Linked Frameworks and Libraries”.

Add the following entry to your Info.plist:

<key>UISupportedExternalAccessoryProtocols</key>
<array>
    <string>com.bixolon.protocol</string>
</array>

Pair the printer with your device. * The default pairing pin is 0000

Usage

The main class necessary to interact with the printer is UPOSPrinterController. Watch out: If an instance of UPOSPrinterController is allocated when running the app in the simulator, it crashes. So you’ll probably want to load the printer controller only when running on an actual device, I’m using a preprocessor define #if TARGET_IPHONE_SIMULATOR and just use a mocked object with the same interface that does nothing on the simulator.

First, create a new instance of UPOSPrinterController and configure it.

self.uposPrinterController = [UPOSPrinterController new];

[self.uposPrinterController setTextEncoding:NSASCIIStringEncoding];
self.uposPrinterController.CharacterSet = 437;

self.deviceList =   (UPOSPrinters*)[_uposPrinterController getRegisteredDevice];

The sample project also clears the device list right there. It seems as if the device list persists which might be the reason this is necessary:

while([self.deviceList getList].count) {
  [self.deviceList removeDevice:[[self.deviceList getList] lastObject]];
}

In order to connect to a printer, it has to be added to the printer controller’s deviceList. You can use device lookup (e.g. refreshBLELookup) to discover devices, but the simplest possibility is to pair the printer and use the paired device:

UPOSPrinter *printer = [[self.deviceList getPairedDevices] firstObject];
[self.deviceList addDevice:printer];
[self.deviceList save];

Then, you’ll have to open the printer, claim and enable it:

// Open Connection to the printer
UPOSPrinter *device  = [[self.deviceList getList] firstObject];
if ([self.uposPrinterController open:device.modelName] != UPOS_SUCCESS) {
  NSLog(@"Error when opening the printer: %@", self.uposPrinterController.ErrorString);
  return;
}
if [self.uposPrinterController claim:5000] != UPOS_SUCCESS) {
  NSLog(@"Error when claiming the printer: %@", self.uposPrinterController.ErrorString);
}
[self printerEnableDisable:YES];

Now the printer is ready to receive data to print:

[self.uposPrinterController printNormal:PTR_S_RECEIPT data:@"Test\n\r"];

Thats it! (to get started, anyway).

Attention: At first I tried to release the printer and close the connection after printing, but it seems that the printer calls are asynchronous and if the connection is closed immediately, nothing is printed. For now, I just keep the connection open for that reason.

Sample Project

A small sample project can be found on github.

Why I think the documentation is bad

The documentation is incredibly detailed. On 116 pages, it describes every class, method and constant in the SDK. It, however, does not tell the reader, how to do anything with the SDK.

Just take for example the documentation for the claim method which was giving me troubles:

This method tries to open the port specified in the device information, and it includes some initialization processes such as memory allocation and initialization.
This method should be called before using the device.
[See Also]
- Constants (Defines) :: Result Code
- [Common] Device Controller Class Reference :: Available Method :: open
- [Printer] Printer Controller Class Reference :: Available Method :: open
- [Common] Device Controller Class Reference :: Available Method :: claim
- [Common] Device Controller Class Reference :: Available Properties :: Claimed
[Declare]
- [Common] Device Controller Class Reference :: Available Method :: claim
[Parameters]
(NSInteger) timeout
- The system will try to execute the corresponding operation for the duration specified
by this parameter.
[Return Value]
NSInteger
- UPOS_SUCCESS if the operation is successful.

Ok. But, when I called claim, I did not get UPOS_SUCCESS but UPOS_E_ILLEGAL. Not too surprising since I did not really know what I needed to do and was just guessing. However, there was no information to be found, why this call was returning this error code, and the only explanation for the error code in the documentation is this:

UPOS_E_ILLEGAL: Illegal access or unsupported function

In my opinion, all the documentation in the provided document belongs directly into the source code (which is entirely undocumented!), and the documentation document should provide a guide to get started just as the one I’m trying to provide here, as well as usage examples for different scenarios.

Markus Chmelar Portrait

Markus Chmelar, MSc

Markus is a technical mastermind and one of the founders of Innovaptor. He studied Computer Engineering at Vienna University of Technology and contributes a valuable diversification to Innovaptor's qualifications. Markus is eager to find innovative solutions to complex problems in order to provide products that are tailored directly to the customers' needs