marklife-label-printer-web-kit
v1.1.4
Published
JavaScript library for BLE label printing with Marklife printers
Downloads
53
Maintainers
Readme
Marklife Label Printer Web Kit
Tested with the Marklife P50S Printer: This library has been specifically tested and verified to work with the Marklife P50S printer (Firmware 2024/2025). While currently optimized for this model (Protocol 0x1F), the library maintains compatibility with legacy models (Protocol 0x10).
marklife-label-printer-web-kit is a JavaScript library designed to handle Bluetooth Low Energy (BLE) label printing using Marklife printers. This library supports both Node.js and browser environments.
GitLab Repository: Marklife Label Printer Web Kit
🚀 Live Demo
Try it now! No installation required.
- Demo URL: https://marklife-lpwk.atokatl.dev/
- Tested Browsers: Chrome, Firefox (Desktop)
- Note: Requires a Bluetooth-capable device.
Table of Contents
- Marklife Label Printer Web Kit
Features
P50S Support:
- Full implementation of Protocol 0x1F (required for new P50S printers).
- Optimized image processing (384px width, opaque).
Robust Communication:
- Flow Control: Implements credit-based flow control (UUID
0xFF03) to prevent buffer overflows and disconnections when printing large images. - Chunking: Automatically splits data into optimal chunks (90 bytes).
- Flow Control: Implements credit-based flow control (UUID
Image Processing:
- BMP image handling for label printing.
- Automatic resizing, centering, and grayscale conversion.
- Proprietary compression algorithm (
dudu.js) support.
Cross-Environment Support:
- Node.js operations using
@abandonware/nobleandjimp. - Browser operations using the Web Bluetooth API.
- High-level handlers (
NodeHandler,BrowserHandler) to simplify integration.
- Node.js operations using
Installation
Install the library from npm:
npm install marklife-label-printer-web-kitAdditional Dependencies
For Node.js, you must install these specific versions to ensure compatibility:
npm install @abandonware/noble
npm install [email protected] # IMPORTANT: v0.16.1 is required. Do not use v1.0+.For Browser projects, no additional dependencies are required if you use a bundler like Webpack or Browserify.
Usage
This library can be used in two ways: a basic, high-level approach using handlers (recommended for most users) or an advanced, low-level approach for more control.
Method 1: Basic Usage (Recommended)
The easiest way to use the library is with the provided handlers, which abstract away the complexity of BLE communication and Flow Control.
Node.js Example (NodeHandler)
The NodeHandler class simplifies the process in a Node.js environment.
const NodeHandler = require('marklife-label-printer-web-kit/examples/handlers/node-handler.js');
const path = require('path');
async function main() {
const handler = new NodeHandler();
const imagePath = path.join(__dirname, './assets/test2_qm.bmp');
try {
// 1. Connect (Auto-scans for 'P50', 'Marklife', etc.)
await handler.connect();
console.log("Connected!");
// 2. Print the image
// The handler takes care of resizing, processing, and flow control.
await handler.printImage(imagePath);
console.log("Print job sent successfully.");
// 3. Disconnect
handler.disconnect();
} catch (error) {
console.error("Error:", error.message);
}
}
main();Browser Example (BrowserHandler)
In the browser, you can use the Web Bluetooth API. The BrowserHandler simplifies this process.
const BrowserHandler = require('marklife-label-printer-web-kit/examples/handlers/browser-handler.js');
const handler = new BrowserHandler();
// This code should be triggered by a user action, like a button click.
async function print() {
const fileInput = document.getElementById('bmpInput');
const file = fileInput.files[0];
if (!file) return alert('Select a file first');
try {
// 1. Connect (Triggers browser pairing dialog)
await handler.connect();
// 2. Prepare and Print
const fileBuffer = await file.arrayBuffer();
await handler.printImage(fileBuffer);
alert("Print job sent successfully.");
// 3. Disconnect
handler.disconnect();
} catch (error) {
console.error("Printing failed:", error);
}
}Method 2: Advanced Usage
For more granular control, you can use the printport module directly. This requires you to manage the BLE connection, Flow Control credits, and data fragmentation manually.
const { Buffer } = require("buffer");
const Jimp = require("jimp");
const noble = require('@abandonware/noble');
const printPort = require("marklife-label-printer-web-kit/lib/printport");
// ... (Connection logic using noble) ...
// On 'discover' characteristic:
// 1. Subscribe to 0xFF03 for Flow Control credits.
// 2. Write to 0xFF02.
// Construct the payload manually:
const fullPayload = Buffer.concat([
printPort.setPaperType(0x20), // 0x20 = Labels
printPort.startPrintjob(), // Protocol 0x1F handshake
printPort.alignPaperStart(), // Align paper
Buffer.from(imageBuffer), // Compressed image data
printPort.stopPrintjob(),
printPort.alignPaperEnd() // Cut/Feed
]);
// Send 'fullPayload' in chunks (e.g., 90 bytes), pausing when credits run out.API Reference
The printport module provides low-level functions for printer communication:
processImageData(imageData): Converts a raw image data object into a printable, compressed format.startPrintjob(): Returns the command buffer to start a print job (Protocol 0x1F).stopPrintjob(): Returns the command buffer to end a print job.alignPaperStart(): Aligns the paper before printing.alignPaperEnd(): Feeds the paper to the tear-off position after printing.setPaperType(type): Sets the type of paper (0x20for Gap/Labels,0x10for Continuous).setDensity(level): Sets the print density (1-15).setSpeed(level): Sets the print speed (0-2).getPrinterBatteryVol(): Queries the battery voltage.
Examples
This repository includes four detailed examples to help you get started:
examples/node_using_handler: (Recommended) High-level Node.js example usingNodeHandler.examples/browser_using_handler: (Recommended) High-level Browser example usingBrowserHandler.examples/node_using_printport: Low-level Node.js example. Shows manual command construction.examples/browser_using_printport: Low-level Browser example. Shows manual Web Bluetooth handling.
Each example folder contains a README.md with specific instructions.
Requirements
Node.js
@abandonware/noble: For BLE device handling.jimp: Must be v0.16.1.
Browser
- A modern browser with Web Bluetooth API support (e.g., Chrome, Edge, Opera).
- Secure Context: Web Bluetooth requires HTTPS or
localhost.
Development Workflow
If you want to modify the library's source code, follow these steps.
1. Locate the Source Code
The core logic of the library is located in the /lib directory.
lib/printport.js: Main API.lib/handlers/: Reusable handlers for Node and Browser.
2. Testing Changes
For Node.js Examples
Changes in /lib are reflected immediately.
sudo node examples/node_using_handler/index.jsFor Browser Examples
You must re-build the bundle after modifying /lib.
cd examples/browser_using_handler
npm run build
# Then serve and open index.htmlIMPORTANT: If you modify any file in the
lib/directory, you MUST runnpm run buildin the browser example directory to regeneratemarklife.bundle.js. The browser cannot see your changes otherwise.
Versioning
This project follows Semantic Versioning (SemVer).
- Major (X.y.z): Breaking changes.
- Minor (x.Y.z): New features (backward compatible).
- Patch (x.y.Z): Bug fixes (backward compatible).
Contributing
Feel free to fork the repository and create pull requests with improvements or bug fixes.
Note: The current examples are designed for .bmp files. Adding support for other formats (PNG, JPG) would be a great feature contribution!
Project History
GitLab Repository: Marklife Label Printer Web Kit
This library is a port and adaptation of an original SDK designed for WeChat Mini Programs (WeiXin Mini Programs). The original source code was provided by the printer manufacturer (Marklife/Phomemo) as a ZIP archive containing the implementation for their WeChat integration.
The Origin: WeChat Framework
The original code (preserved in lib/archive) was written specifically for the WeChat ecosystem, which differs significantly from standard Web or Node.js environments:
- The
wxGlobal Object: Instead ofwindoworglobal, the framework relies on thewxobject. The original code used APIs likewx.createBLEConnection,wx.writeBLECharacteristicValue, andwx.canvasGetImageData. - No DOM: Similar to React Native or Flutter, Mini Programs do not have a DOM. This meant standard canvas operations for image processing had to be rewritten using Jimp (for Node.js) and pure Canvas API (for Browser) to replace
wx.canvasGetImageData. - File Structure: The original project used
.wxml(HTML),.wxss(CSS),.js, and.jsonfiles typical of the WeiXin framework.
The Porting Process
To make this SDK usable in standard environments, we performed a complete reverse-engineering and porting process:
- Bluetooth Layer: Replaced
wxBLE APIs withnoblefor Node.js and Web Bluetooth API for browsers. - Image Processing: Replaced
wxcanvas APIs withjimpand standard HTML5 Canvas. - Core Logic: The proprietary compression algorithms (found in
lib/common/dudu.js) were isolated and preserved, as they are critical for communicating with the printer's firmware.
This project essentially "liberated" the driver from the closed WeChat ecosystem, making it available for general web and desktop application development.
License
This library is licensed under a custom agreement between MarkLife and MickeyGR. Redistribution or modification is subject to strict limitations.
Please see the LICENSE file for the full terms and conditions.
For permissions or inquiries, contact:
- MarkLife: [email protected] | www.marklifeprinter.com
- MickeyGR: [email protected] | mickeygr.atokatl.dev
Notes
- Device Name: Ensure your printer advertises a name starting with "P50", "Marklife", or "Printer".
- P50S Specifics: The library enforces a 384px width for images to ensure compatibility with the P50S firmware.
