UNPKG

marklife-label-printer-web-kit

Version:

JavaScript library for BLE label printing with Marklife printers

333 lines (223 loc) 12.3 kB
# Marklife Label Printer Web Kit [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y31Q3R29) **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](https://gitlab.com/marklife/marklife-label-printer-web-kit) --- ## 🚀 Live Demo **Try it now!** No installation required. - **Demo URL**: [https://marklife-lpwk.atokatl.dev/](https://marklife-lpwk.atokatl.dev/) - **Tested Browsers**: Chrome, Firefox (Desktop) - **Note**: Requires a Bluetooth-capable device. --- ## Table of Contents - [Marklife Label Printer Web Kit](#marklife-label-printer-web-kit) - [Table of Contents](#table-of-contents) - [Features](#features) - [Installation](#installation) - [Additional Dependencies](#additional-dependencies) - [Usage](#usage) - [Method 1: Basic Usage (Recommended)](#method-1-basic-usage-recommended) - [Node.js Example (`NodeHandler`)](#nodejs-example-nodehandler) - [Browser Example (`BrowserHandler`)](#browser-example-browserhandler) - [Method 2: Advanced Usage](#method-2-advanced-usage) - [API Reference](#api-reference) - [Examples](#examples) - [Requirements](#requirements) - [Node.js](#nodejs) - [Browser](#browser) - [Development Workflow](#development-workflow) - [1. Locate the Source Code](#1-locate-the-source-code) - [2. Testing Changes](#2-testing-changes) - [Contributing](#contributing) - [License](#license) - [Notes](#notes) --- ## 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). - **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/noble` and `jimp`. - Browser operations using the Web Bluetooth API. - High-level handlers (`NodeHandler`, `BrowserHandler`) to simplify integration. --- ## Installation Install the library from npm: ```bash npm install marklife-label-printer-web-kit ``` ### Additional Dependencies For **Node.js**, you must install these specific versions to ensure compatibility: ```bash npm install @abandonware/noble npm install jimp@0.16.1 # 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. ```javascript 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. ```javascript 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. ```javascript 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 (`0x20` for Gap/Labels, `0x10` for 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 using `NodeHandler`. - **`examples/browser_using_handler`**: **(Recommended)** High-level Browser example using `BrowserHandler`. - **`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`](https://www.npmjs.com/package/@abandonware/noble): For BLE device handling. - [`jimp`](https://www.npmjs.com/package/jimp): **Must be v0.16.1**. ### Browser - A modern browser with [Web Bluetooth API](https://developer.mozilla.org/en-US/docs/Web/API/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. ```bash sudo node examples/node_using_handler/index.js ``` #### For Browser Examples You must **re-build** the bundle after modifying `/lib`. ```bash cd examples/browser_using_handler npm run build # Then serve and open index.html ``` > **IMPORTANT**: If you modify any file in the `lib/` directory, you **MUST** run `npm run build` in the browser example directory to regenerate `marklife.bundle.js`. The browser cannot see your changes otherwise. --- ## Versioning This project follows [Semantic Versioning](https://semver.org/) (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](https://gitlab.com/marklife/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: 1. **The `wx` Global Object**: Instead of `window` or `global`, the framework relies on the `wx` object. The original code used APIs like `wx.createBLEConnection`, `wx.writeBLECharacteristicValue`, and `wx.canvasGetImageData`. 2. **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`. 3. **File Structure**: The original project used `.wxml` (HTML), `.wxss` (CSS), `.js`, and `.json` files 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 `wx` BLE APIs with **`noble`** for Node.js and **Web Bluetooth API** for browsers. - **Image Processing**: Replaced `wx` canvas APIs with **`jimp`** and 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](./LICENSE) file for the full terms and conditions. For permissions or inquiries, contact: - **MarkLife**: marklifeservice@gmail.com | [www.marklifeprinter.com](https://www.marklifeprinter.com) - **MickeyGR**: mickeyanthonygudiel@gmail.com | [mickeygr.atokatl.dev](https://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.