UNPKG

@mmote/niimblue-node

Version:

Headless clients for niimbluelib. Command line interface, simple REST server are also included.

139 lines (138 loc) 5.58 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.scan = exports.print = exports.info = exports.connected = exports.disconnect = exports.connect = exports.index = exports.setDebug = void 0; const niimbluelib_1 = require("@mmote/niimbluelib"); const sharp_1 = __importDefault(require("sharp")); const zod_1 = require("zod"); const headless_ble_impl_1 = require("../client/headless_ble_impl"); const image_encoder_1 = require("../image_encoder"); const utils_1 = require("../utils"); const simple_server_1 = require("./simple_server"); const headless_serial_impl_1 = require("../client/headless_serial_impl"); let client = null; let debug = false; const ConnectSchema = zod_1.z.object({ transport: zod_1.z.enum(["serial", "ble"]), address: zod_1.z.string(), }); const ScanSchema = zod_1.z.object({ transport: zod_1.z.enum(["serial", "ble"]), timeout: zod_1.z.number().default(5000), }); const [firstTask, ...otherTasks] = niimbluelib_1.printTaskNames; const PrintSchema = zod_1.z .object({ printDirection: zod_1.z.enum(["left", "top"]).optional(), printTask: zod_1.z.enum([firstTask, ...otherTasks]).optional(), quantity: zod_1.z.number().min(1).default(1), labelType: zod_1.z.number().min(1).default(niimbluelib_1.LabelType.WithGaps), density: zod_1.z.number().min(1).default(3), imageBase64: zod_1.z.string().optional(), imageUrl: zod_1.z.string().optional(), labelWidth: zod_1.z.number().positive().optional(), labelHeight: zod_1.z.number().positive().optional(), threshold: zod_1.z.number().min(1).max(255).default(128), imagePosition: zod_1.z .enum(["centre", "top", "right top", "right", "right bottom", "bottom", "left bottom", "left", "left top"]) .default("centre"), imageFit: zod_1.z.enum(["contain", "cover", "fill", "inside", "outside"]).default("contain"), }) .refine(({ imageUrl, imageBase64 }) => { return !!imageUrl !== !!imageBase64; }, { message: "imageUrl or imageBase64 must be defined", path: ["image"] }); const setDebug = (v) => { debug = v; }; exports.setDebug = setDebug; const assertConnected = () => { if (!client?.isConnected()) { throw new simple_server_1.RestError("Not connected", 400); } }; const index = () => ({ message: "Server is working" }); exports.index = index; const connect = async (r) => { const data = await (0, simple_server_1.readBodyJson)(r, ConnectSchema); if (client?.isConnected()) { throw new simple_server_1.RestError("Already connected", 400); } client = (0, utils_1.initClient)(data.transport, data.address, debug); await client.connect(); return { message: "Connected" }; }; exports.connect = connect; const disconnect = async () => { assertConnected(); await client.disconnect(); client = null; return { message: "Disconnected" }; }; exports.disconnect = disconnect; const connected = async () => { return { connected: !!client?.isConnected() }; }; exports.connected = connected; const info = async () => { assertConnected(); return { printerInfo: client.getPrinterInfo(), modelMetadata: client.getModelMetadata(), detectedPrintTask: client.getPrintTaskType(), }; }; exports.info = info; const print = async (r) => { assertConnected(); const options = await (0, simple_server_1.readBodyJson)(r, PrintSchema); let image; if (options.imageBase64 !== undefined) { image = await (0, utils_1.loadImageFromBase64)(options.imageBase64); } else if (options.imageUrl !== undefined) { image = await (0, utils_1.loadImageFromUrl)(options.imageUrl); } else { throw new simple_server_1.RestError("Image is not defined", 400); } image = image.flatten({ background: "#fff" }); if (options.labelWidth !== undefined && options.labelHeight !== undefined) { image = image.resize(options.labelWidth, options.labelHeight, { kernel: sharp_1.default.kernel.nearest, fit: options.imageFit, position: options.imagePosition, background: "#fff", }); } image = image.threshold(options.threshold); // await image.toFile("tmp.png"); const printDirection = options.printDirection ?? client.getModelMetadata()?.printDirection; const printTask = options.printTask ?? client.getPrintTaskType(); const encoded = await image_encoder_1.ImageEncoder.encodeImage(image, printDirection); if (printTask === undefined) { throw new simple_server_1.RestError("Unable to detect print task, please set it manually", 400); } if (debug) { console.log("Print task:", printTask); } await (0, utils_1.printImage)(client, printTask, encoded, { quantity: options.quantity, labelType: options.labelType, density: options.density, }); return { message: "Printed" }; }; exports.print = print; const scan = async (r) => { const options = await (0, simple_server_1.readBodyJson)(r, ScanSchema); if (options.transport === "ble") { return { devices: await headless_ble_impl_1.NiimbotHeadlessBleClient.scan(options.timeout) }; } else if (options.transport === "serial") { return { devices: await headless_serial_impl_1.NiimbotHeadlessSerialClient.scan() }; } throw new simple_server_1.RestError("Invalid transport", 400); }; exports.scan = scan;