Skip to content

jpurnell/T02Protocol

Repository files navigation

T02Protocol

A Swift package for communicating with Phomemo T02 thermal printers via Bluetooth Low Energy.

Swift Version Platforms License

Features

  • Complete T02 Protocol Implementation - ESC/POS command generation
  • Bluetooth Low Energy Support - CoreBluetooth integration for macOS/iOS
  • Automatic Image Processing - Converts any image to T02 format
  • Type-Safe API - Swift enums for commands and settings
  • Cross-Platform - Works on macOS 13+ and iOS 16+
  • Comprehensive Tests - Full test suite with Swift Testing
  • Command-Line Tool - Included for testing and standalone use

Quick Start

Add to Your Project

Via Xcode:

  1. File → Add Package Dependencies...
  2. Enter: https://github.com/jpurnell/T02Protocol
  3. Select version and add to target

Via Package.swift:

dependencies: [
    .package(url: "https://github.com/jpurnell/T02Protocol", from: "0.0.1")
]

Basic Usage

import T02Protocol
import UIKit

// Create protocol instance
let protocol = T02Protocol()

// Load your image
let image = UIImage(named: "label")!

// Generate print data
let printData = try protocol.generatePrintData(from: image, feedLines: 4)

// Send to printer via Bluetooth
yourBluetoothManager.send(data: printData)

Command-Line Tool

The package includes a ready-to-use printing tool:

# Print an image
swift run T02PrintTool bt image.png

# Create test image
swift run T02PrintTool create test.png

# Debug protocol output
swift run T02PrintTool debug image.png

Note: Printer must be powered on within last 30 seconds (BLE advertising period).

API Overview

Protocol Generation

let protocol = T02Protocol()

// Complete print job
let data = try protocol.generatePrintData(from: image, feedLines: 4)

// Custom feed lines (0-255)
let data = try protocol.generatePrintData(from: image, feedLines: 10)

Individual Commands

// Initialize printer
let initCmd = protocol.cmdInitPrinter()

// Set alignment
let centerCmd = protocol.cmdSetJustification(.center)
let leftCmd = protocol.cmdSetJustification(.left)
let rightCmd = protocol.cmdSetJustification(.right)

// Feed paper
let feedCmd = try protocol.cmdFeedLines(4)

// Raster image header
let header = protocol.cmdRasterHeader(
    widthBytes: 48,
    lines: 200,
    mode: .normal
)

Image Conversion

// Convert image to T02 format (384px wide, 1-bit monochrome)
let converted = try protocol.convertImage(yourImage)

Constants

T02Protocol.widthDots        // 384 (50mm at 203 DPI)
T02Protocol.widthBytes       // 48 (384 / 8)
T02Protocol.dpi              // 203
T02Protocol.maxLinesPerBlock // 255 (protocol limit)
T02Protocol.defaultFeedLines // 4

Enums

Justification

enum Justification {
    case left
    case center
    case right
}

PrintMode

enum PrintMode {
    case normal        // 1x size
    case doubleWidth   // 2x width
    case doubleHeight  // 2x height
    case quadruple     // 4x size
}

Complete Examples

macOS App

import T02Protocol
import CoreBluetooth
import AppKit

class PrinterManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    let protocol = T02Protocol()
    var centralManager: CBCentralManager!

    func print(image: NSImage) {
        // Generate print data
        let printData = try! protocol.generatePrintData(from: image)

        // Connect and send via CoreBluetooth
        // ... BLE implementation ...
    }
}

iOS App

import T02Protocol
import UIKit

class PhotoPrinter {
    let protocol = T02Protocol()

    func print(photo: UIImage) {
        do {
            let printData = try protocol.generatePrintData(from: photo, feedLines: 4)
            sendViaBluetooth(printData)
        } catch {
            print("Print failed: \(error)")
        }
    }
}

SwiftUI Integration

import SwiftUI
import T02Protocol

struct PrinterView: View {
    @State private var image: UIImage?
    let protocol = T02Protocol()

    var body: some View {
        VStack {
            if let image = image {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()

                Button("Print") {
                    printImage(image)
                }
            }
        }
    }

    func printImage(_ image: UIImage) {
        do {
            let data = try protocol.generatePrintData(from: image)
            // Send to printer
        } catch {
            print("Error: \(error)")
        }
    }
}

Protocol Details

ESC/POS Commands

ESC @ (0x1b 0x40)            - Initialize printer
ESC a n (0x1b 0x61 n)        - Set justification (0=left, 1=center, 2=right)
ESC d n (0x1b 0x64 n)        - Feed n lines (0-255)
GS v 0 (0x1d 0x76 0x30)      - Raster bit image

Image Processing Pipeline

Input → Resize to 384px → Grayscale → Invert → 1-bit → Pack bytes → Protocol

Data Structure

[Header]
  ESC @ (init)
  ESC a 1 (center)

[Body - repeated for blocks]
  GS v 0 (raster header)
    - width: 48 bytes
    - lines: 1-255
  [bitmap data]

[Footer]
  ESC d N (feed)

Testing

# Run all tests
swift test

# Run specific test
swift test --filter T02ProtocolTests

# With verbose output
swift test --verbose

Requirements

  • Swift: 5.9 or later
  • macOS: 13.0 (Ventura) or later
  • iOS: 16.0 or later
  • Xcode: 15.0 or later (for development)

Hardware

  • Printer: Phomemo T02
  • Connection: Bluetooth Low Energy (BLE)
  • Paper Width: 50mm
  • Resolution: 203 DPI
  • Print Width: 384 dots (48 bytes)

Bluetooth Implementation

This package provides the protocol layer. For complete BLE printing:

  1. Scan for devices named "T02"
  2. Connect using CoreBluetooth
  3. Discover services and writable characteristics
  4. Generate print data with this package
  5. Send in small chunks (20 bytes recommended)
  6. Wait 50ms between chunks

See T02PrintTool/CoreBluetoothConnection.swift for reference implementation.

Error Handling

do {
    let data = try protocol.generatePrintData(from: image)
} catch T02Protocol.ProtocolError.imageHeightExceedsMaximum {
    // Image too tall
} catch T02Protocol.ProtocolError.invalidFeedLines {
    // Feed lines out of range
} catch {
    // Other errors
}

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Based on reverse-engineered ESC/POS protocol
  • Python reference implementation compatibility
  • Community contributions and testing

Related Projects

  • phomemo-tools - Linux CUPS drivers
  • Original protocol research and implementation

Support

  • Documentation: See inline code documentation
  • Examples: Check INTEGRATION_EXAMPLE.md
  • Issues: GitHub issue tracker
  • Discussions: GitHub discussions

About

Swift package for direct Phomemo T02 thermal printer communication via Bluetooth Low Energy

Resources

License

Stars

Watchers

Forks

Packages