### GET /public_resources/static_resources/devices.json Source: https://context7.com/multimote/niimbot-wiki/llms.txt Fetches a static JSON file containing information about NIIMBOT devices. ```APIDOC ## GET /public_resources/static_resources/devices.json ### Description Retrieves a static JSON file that lists available NIIMBOT devices and their specifications. This endpoint is useful for obtaining a comprehensive list of supported hardware. ### Method GET ### Endpoint /public_resources/static_resources/devices.json ### Parameters None ### Request Example ```bash curl -X GET "https://oss-print.niimbot.com/public_resources/static_resources/devices.json" ``` ### Response #### Success Response (200) - **devices** (array) - An array of device objects, each containing details like machine name, DPI, printhead pixel count, paper types, and density range. #### Response Example ```json [ { "machineName": "B1", "dpiValue": 203, "printheadPixelCount": 384, "paperTypes": ["label"], "densityMin": 1, "densityMax": 15, "printDirection": 0 } // ... more devices ] ``` ``` -------------------------------- ### Bash NIIMBOT Cloud API - Get Device List Source: https://context7.com/multimote/niimbot-wiki/llms.txt Demonstrates how to fetch all NIIMBOT printer hardware specifications using a `curl` command. This includes details like DPI, printhead size, and supported label types from the official cloud API. ```bash # Get all printer hardware specifications curl -X GET "https://print.niimbot.com/api/hardware/list" \ -H "Content-Type: application/json" | jq '.' ``` -------------------------------- ### GET /api/hardware/list Source: https://context7.com/multimote/niimbot-wiki/llms.txt Fetches a list of all NIIMBOT printer models and their specifications via the cloud API. ```APIDOC ## GET /api/hardware/list ### Description Fetches all NIIMBOT printer specifications from the cloud API. This endpoint provides dynamic information about available printer models. ### Method GET ### Endpoint /api/hardware/list ### Parameters None ### Request Example ```python import requests response = requests.get("https://print.niimbot.com/api/hardware/list") print(response.json()) ``` ### Response #### Success Response (200) - **data** (array) - An array of printer model objects, each containing details like machine name, device type ID, DPI, printhead pixel count, paper types, and density range. #### Response Example ```json { "code": 200, "message": "Success", "data": [ { "machineName": "B1", "deviceType": 4096, "dpiValue": 203, "printheadPixelCount": 384, "paperTypes": ["label"], "densityMin": 1, "densityMax": 15, "printDirection": 0 } // ... more models ] } ``` ``` -------------------------------- ### Simple Request Packet Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Explains the format of a 'Simple Request Packet', characterized by a Request ID, Data Length of 1, and Data value of 1. Includes an example for the RfidInfo command. ```APIDOC ## Simple Request Packet This packet type is used for simple requests where the data payload is minimal. ### Format * **Head**: `0x55 0x55` * **Command**: The Request ID of the command. * **Data Length**: Always `0x01`. * **Data**: Always `0x01`. * **Checksum**: Calculated as `Command ^ 0x01 ^ 0x01`, which simplifies to just the `Command` value. * **Tail**: `0xAA 0xAA` ### Example (RfidInfo) ``` 55 55 1a 01 01 1a aa aa │ │ │ │ │ │ │ └─ Checksum (1a^01^01) │ │ └─ Data │ └─ Data length └─ RfidInfo command ``` ``` -------------------------------- ### Other Packets Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md A collection of miscellaneous packet examples for common operations like retrieving device serial numbers, RFID data, and controlling Bluetooth sounds. ```APIDOC ## Miscellaneous Commands ### Description This section provides examples of various other commands used to interact with the Niimbot printer for different functionalities. ### Examples #### Get Device Serial Number - **Command:** `55 55 40 01 0b 4a aa aa` - **Description:** Retrieves the unique serial number of the device. #### Get RFID Data - **Command:** `55 55 1a 01 01 1a aa aa` - **Description:** Fetches RFID data associated with the printer or consumables. #### Enable Bluetooth Connection Sound - **Command:** `55 55 58 03 01 01 01 5a aa aa` - **Description:** Enables the sound notification for Bluetooth connection events. #### Disable Bluetooth Connection Sound - **Command:** `55 55 58 03 01 01 00 5b aa aa` - **Description:** Disables the sound notification for Bluetooth connection events. ``` -------------------------------- ### PrintStart Command Variants Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Details the different byte structures for the PrintStart command, used to initiate printing. Variants include 7-byte and 9-byte formats, with differing fields for page color, total pages, and speed. ```APIDOC ## PrintStart Command ### Description Initiates the printing process. This command has variations in its byte structure depending on the printer model and features. ### Command Variants #### 7 Bytes (B1 and newer printers) ``` 55 55 01 07 00 01 00 00 00 00 00 XX aa aa │ │ └──┤ └──┴──┴──┘ │ │ │ │ │ Always 0 │ └─ Checksum │ │ │ └─ Page color (unknown use) │ │ └─ Total pages (sum of page quantity of each page) │ └─ Data length └─ PrintStart command ``` #### 9 Bytes ``` 55 55 01 09 00 01 00 00 00 00 00 00 00 XX aa aa │ │ └──┤ └──┴──┴──┘ │ │ │ │ │ │ │ Always 0 │ │ │ └─ Checksum │ │ │ │ │ └─ Some flag (unknown use) │ │ │ │ └─ Speed (0 - higher quality and slower speed, 1 - lower quality and faster speed) │ │ │ └─ Page color (unknown use) │ │ └─ Total pages (sum of page quantity of each page) │ └─ Data length └─ PrintStart command ``` ### Parameters - **Header**: `55 55` (Start of packet) - **Command**: `01` (PrintStart) - **Data Length**: Variable (07 or 09 bytes) - **Always 0**: Typically `00 00 00 00` - **Page Color**: `XX` (Unknown use) - **Total Pages**: Sum of page quantities - **Speed**: `0` or `1` (for 9-byte variant) - **Some flag**: (for 9-byte variant, unknown use) - **Checksum**: `aa aa` (End of packet) ``` -------------------------------- ### PrintStart Command Variations Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Details the different packet formats for the PrintStart command, which vary depending on the printer model (e.g., D11, B21, D110). ```APIDOC ## PrintStart Command The `PrintStart` command can have different packet formats depending on the printer model. ### Format 1 (1 byte data - used in D11, B21, D110) ``` 55 55 02 01 01 XX aa aa │ │ │ │ │ │ │ └─ Checksum │ │ └─ Always 1 │ └─ Data length └─ PrintStart command (0x02) ``` ### Format 2 (2 bytes data) ``` 55 55 01 02 00 01 XX aa aa │ │ └──┤ │ │ │ │ └─ Checksum │ │ └─ Total pages (sum of page quantity of each page) │ └─ Data length └─ PrintStart command (0x01) ``` ``` -------------------------------- ### Packet Structure and Building Source: https://context7.com/multimote/niimbot-wiki/llms.txt Demonstrates how to construct NIIMBOT protocol packets, including header, tail, command, data length, payload, and checksum calculation. ```APIDOC ## POST /api/packets ### Description Constructs a NIIMBOT protocol packet with the specified command and data. ### Method POST ### Endpoint /api/packets #### Request Body - **command** (integer) - Required - The command byte for the packet. - **data** (bytes) - Required - The payload data for the packet. ### Request Example ```json { "command": 26, "data": "01" } ``` ### Response #### Success Response (200) - **packet** (string) - The constructed NIIMBOT packet in hexadecimal format. #### Response Example ```json { "packet": "55551a01011aaaaa" } ``` ``` -------------------------------- ### Simple Response Packet Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Describes the 'Simple Response Packet', which shares the same format as the Simple Request Packet but is used for responses. An example for In_SetDensity is provided. ```APIDOC ## Simple Response Packet This packet type is used for simple responses and follows the same structure as the Simple Request Packet. ### Format * **Head**: `0x55 0x55` * **Command**: The Response ID of the command. * **Data Length**: Always `0x01`. * **Data**: Typically `0x01` for success and `0x00` for error, or other specific values depending on the command. * **Checksum**: Calculated as `Command ^ 0x01 ^ 0x01`, which simplifies to just the `Command` value. * **Tail**: `0xAA 0xAA` ### Example (In_SetDensity) ``` 55 55 31 01 01 31 aa aa │ │ │ │ │ │ │ └─ Checksum (31^01^01) │ │ └─ Data (1 - success, 0 - error) │ └─ Data length └─ In_SetDensity command ``` ``` -------------------------------- ### Flash firmware via jcPrinterSdk using Python Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/firmware/flashing-firmware.md This script demonstrates how to communicate with the jcPrinter websocket server to select a printer, enable logging, calculate firmware CRC, and initiate the update process. It requires the 'websocket-client' library and an active connection to the local jcprinter service. ```python import websocket import json from zlib import crc32 websocket_url = "ws://localhost:37989" filename = "/absolute/path/to/firmware.bin" version = "3.01" ws = websocket.WebSocket() ws.connect(websocket_url) # receiving info about connected printers req = {"apiName": "getAllPrinters"} ws.send(json.dumps(req)) connectData = {} message = json.loads(ws.recv()) if message.get("resultAck", None) and message["resultAck"].get("info", None): info = json.loads(message["resultAck"]["info"]) connectData["printerName"] = [*info][0] connectData["port"] = int(info[connectData["printerName"]]) # connect Printer req = {"apiName": "selectPrinter", "parameter": connectData} ws.send(json.dumps(req)) message = ws.recv() print(json.loads(message)) # enable detailed logging to console req = {"apiName": "enableConsoleAllLog", "parameter": {"isEnable": 1}} ws.send(json.dumps(req)) while True: message = json.loads(ws.recv()) if message.get("apiName", None) == req["apiName"]: break print(message) with open(filename, "rb") as f: fw = f.read() crc = crc32(fw) print(f"Firmware CRC: {crc:08X}") req = { "apiName": "updateFirmware", "parameter": { "fileName": filename, "strSwVersion": version, "strCrc": f"{crc:08X}", }, } ws.send(json.dumps(req)) while True: message = json.loads(ws.recv()) if message.get("apiName", None) == req["apiName"]: print(message) resAck = message.get("resultAck", None) if resAck and resAck.get("result", None) == 0: break # close the websocket connection ws.close() ``` -------------------------------- ### USB Serial Debug Commands Source: https://context7.com/multimote/niimbot-wiki/llms.txt This section covers accessing diagnostic commands via USB serial connection when the printer is in charge mode. It provides examples for connecting and sending commands to retrieve hardware information, firmware version, and perform tests. ```APIDOC ## USB Serial Debug Commands Access diagnostic commands when the printer is in charge mode (USB connected, power off). These commands provide hardware info, firmware version, and test functions. ### Method Serial Communication (USB) ### Endpoint `/dev/ttyUSBx` (Linux/macOS) or `COMx` (Windows), typically at 115200 baud. ### Description Connect to the printer's serial port using a terminal emulator or a serial communication library. Send specific commands prefixed with `#` for information retrieval or test commands for hardware functions. ### Parameters #### Command Format Commands are sent as strings, often terminated by a newline character (`\n`). #### Common Commands - **`#10001`**: Get hardware version and printer name. - **`#10003`**: Get firmware version. - **`test beep`**: Play a sound. - **`test motor 50 100`**: Run motor at specified speed and duration (values may vary). - **`test motor `**: Stop motor. - **`test get sensor`**: Read sensor data. ### Request Example (Sending a command) ```python import serial port = "/dev/ttyUSB0" # Or your printer's COM port command = "#10001" with serial.Serial(port, 115200, timeout=2) as ser: ser.write(f"{command}\n".encode()) response = ser.readline().decode().strip() print(response) ``` ### Response Responses are typically returned as strings, often prefixed with the command identifier. #### Example Response (`#10001`) ``` #10001:V13.10,D110-G326030306,1 ``` * `V13.10`: Hardware Version * `D110-G326030306`: Printer Model/Serial Info * `1`: Status indicator #### Example Response (`#10003`) ``` #10003:13.14*21# ``` * `13.14`: Firmware Version * `*21#`: Checksum/Status indicator ``` -------------------------------- ### Firmware Flashing via WebSocket Source: https://context7.com/multimote/niimbot-wiki/llms.txt This section details how to flash firmware to NIIMBOT printers using the jcPrinterSdk WebSocket server. It includes steps for connecting, selecting a printer, and initiating the firmware update process. ```APIDOC ## Firmware Flashing via WebSocket Flash firmware to NIIMBOT printers using the jcPrinterSdk WebSocket server that comes with the official NIIMBOT Windows application. ### Method WebSocket ### Endpoint `ws://localhost:37989` ### Description This process involves connecting to the WebSocket server, discovering and selecting a printer, reading the firmware file, calculating its CRC, and then sending the firmware update command. ### Parameters #### Request Body (for `updateFirmware` command) - **apiName** (string) - Required - Must be `"updateFirmware"`. - **parameter** (object) - Required - Contains firmware update details. - **fileName** (string) - Required - Path to the firmware file. - **strSwVersion** (string) - Required - The new firmware version string. - **strCrc** (string) - Required - The CRC32 checksum of the firmware file, formatted as an 8-digit hexadecimal string (e.g., `"0A1B2C3D"`). ### Request Example ```json { "apiName": "updateFirmware", "parameter": { "fileName": "/path/to/B1_firmware.bin", "strSwVersion": "5.20", "strCrc": "A1B2C3D4" } } ``` ### Response #### Success Response (200) - **apiName** (string) - Indicates the command that was processed (`"updateFirmware"`). - **resultAck** (object) - Acknowledgment of the command result. - **result** (integer) - 0 indicates success, other values indicate failure. - **progress** (integer, optional) - Current progress of the firmware update (e.g., percentage). - **message** (string, optional) - A message describing the result or progress. #### Response Example (Success) ```json { "apiName": "updateFirmware", "resultAck": { "result": 0, "message": "Firmware flash complete!" } } ``` #### Response Example (Progress) ```json { "apiName": "updateFirmware", "resultAck": { "result": 1, "progress": 50, "message": "Flashing block 50 of 100" } } ``` ``` -------------------------------- ### List of Packet Commands Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Provides a comprehensive list of commands supported by the Niimbot printers, including their request and response IDs, and whether they are simple OUT or IN packets. ```APIDOC ## List of Packet Commands This table outlines the available commands, their associated IDs, and response IDs. | Request ID | Name | Response ID(s) | [Simple OUT](#simple-request-packet) | [Simple IN](#simple-response-packet) | |---|---|---|---|---| | 0x01 | [PrintStart](#printstart) | 0x02 | ❌ | ✅ | | 0x03 | PageStart | 0x04 | ✅ | ✅ | | 0x05 | PrinterLog | 0x06 | ✅ | ❌ | | 0x0b | AntiFake | 0x0c | ✅ | ❌ | | 0x0d | GetPrintQuality | 0x0d | ❌ | ❌ | | 0x13 | [SetPageSize](#setpagesize) | 0x14 | ❌ | ✅ | | 0x15 | PrintQuantity | 0x16 | ❌ | ✅ | | 0x1a | RfidInfo | 0x1b | ✅ | ❌ | | 0x1c | RfidInfo2 | 0x1d | ✅ | ❌ | | 0x20 | PrintClear | 0x30 | ✅ | ✅ | | 0x21 | SetDensity | 0x31 | ❌ | ✅ | | 0x23 | SetLabelType | 0x33 | ❌ | ✅ | | 0x27 | SetAutoShutdownTime | 0x37 | ❌ | ✅ | | 0x28 | PrinterReset | 0x38 | ✅ | ❌ | | 0x40 | PrinterInfo | 0x4f, 0x47, 0x4d, 0x4a, 0x41, 0x4c, 0x43, 0x46, 0x48, 0x4b, 0x49, 0x42 | ✅ | ❌ | | 0x54 | RfidSuccessTimes | 0x64 | ✅ | ❌ | | 0x58 | SoundSettings | 0x68 | ❌ | ❌ | | 0x59 | CalibrateHeight | 0x69 | ❌ | ❓ | | 0x5a | PrintTestPage | 0x6a | ✅ | ✅ | | 0x70 | WriteRFID | 0x71 | ❓ | ❓ | | 0x83 | [PrintBitmapRowIndexed](#printbitmaprowindexed) | | ❌ | ❌ | | 0x84 | [PrintEmptyRow](#printemptyrow) | | ❌ | ❌ | | 0x85 | [PrintBitmapRow](#printbitmaprow) | | ❌ | ❌ | | 0x8e | LabelPositioningCalibration | 0x8f | ✅ | ✅ | | 0xa3 | PrintStatus | 0xb3 | ✅ | ❌ | | 0xa5 | PrinterStatusData | 0xb5 | ✅ | ❌ | | 0xaf | PrinterConfig | 0xbf | ❌ | ❌ | | 0xc1 | Connect | 0xc2 | ✅ | ❌ | | 0xda | CancelPrint | 0xd0 | ✅ | ✅ | | 0xdc | [Heartbeat](#heartbeat) | 0xde, 0xdf, 0xdd, 0xd9 | ❌ | ❌ | | 0xe3 | PageEnd | 0xe4 | ✅ | ✅ | | 0xf3 | PrintEnd | 0xf4 | ✅ | ✅ | | 0xf5 | StartFirmwareUpgrade | 0xf6 | ❌ | ✅ | ### CRC32 Packets | Request ID | Name | |---|---| | 0x91 | FirmwareCrc | | 0x92 | FirmwareCommit | | 0x9b | FirmwareChunk | | 0x9c | FirmwareNoMoreChunks | ### Printer Only Commands | Request ID | Name | Client response ID | CRC32 | |---|---|---|---| | 0xe0 | In_PrinterPageIndex | | | | 0x90 | In_RequestFirmwareCrc | 0x91 | ✅ | | 0x9a | In_RequestFirmwareChunk | 0x9b | ✅ | | 0x9d | In_FirmwareCheckResult | | ✅ | | 0x9e | In_FirmwareResult | | ✅ | ``` -------------------------------- ### Connect to NIIMBOT Printer via BLE (JavaScript) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Establishes a Bluetooth Low Energy connection to a NIIMBOT printer using the Web Bluetooth API. It requests the device, connects to the GATT server, gets the service and characteristic, and subscribes to notifications for printer responses. This enables real-time communication with the printer. ```javascript // Web Bluetooth API connection to NIIMBOT printer const SERVICE_UUID = 'e7810a71-73ae-499d-8c15-faa9aef0c3f2'; const CHARACTERISTIC_UUID = 'bef8d6c9-9c21-4c9e-b632-bd58c1009f9f'; async function connectPrinter() { // Request device with NIIMBOT service const device = await navigator.bluetooth.requestDevice({ filters: [{ services: [SERVICE_UUID] }], optionalServices: [SERVICE_UUID] }); const server = await device.gatt.connect(); const service = await server.getPrimaryService(SERVICE_UUID); const characteristic = await service.getCharacteristic(CHARACTERISTIC_UUID); // Subscribe to notifications for printer responses await characteristic.startNotifications(); characteristic.addEventListener('characteristicvaluechanged', (event) => { const value = new Uint8Array(event.target.value.buffer); console.log('Printer response:', Array.from(value).map(b => b.toString(16).padStart(2, '0')).join(' ')); }); return characteristic; } // Send connect command (0xC1) async function sendConnectCommand(characteristic) { const packet = new Uint8Array([0x03, 0x55, 0x55, 0xC1, 0x01, 0x01, 0xC1, 0xAA, 0xAA]); await characteristic.writeValueWithoutResponse(packet); } // Usage const printer = await connectPrinter(); await sendConnectCommand(printer); ``` -------------------------------- ### Print Bitmap Row Commands (Python) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Sends image data row by row using different encoding methods. Supports full pixel data, indexed pixel positions for sparse rows, and blank rows. Requires a `build_packet` helper function. ```python def print_bitmap_row(row_num: int, pixel_data: bytes, repeat: int = 1) -> bytes: """Build PrintBitmapRow packet (0x85) for full row data""" command = 0x85 row_bytes = row_num.to_bytes(2, 'big') # Count black pixels (non-zero bits) black_count = sum(bin(b).count('1') for b in pixel_data) black_bytes = bytes([0x00]) + black_count.to_bytes(2, 'little') repeat_byte = bytes([repeat]) data = row_bytes + black_bytes + repeat_byte + pixel_data return build_packet(command, data) def print_empty_row(row_num: int, repeat: int = 1) -> bytes: """Build PrintEmptyRow packet (0x84) for blank rows""" command = 0x84 row_bytes = row_num.to_bytes(2, 'big') repeat_byte = bytes([repeat]) data = row_bytes + repeat_byte return build_packet(command, data) def print_bitmap_row_indexed(row_num: int, pixel_positions: list, repeat: int = 1) -> bytes: """Build PrintBitmapRowIndexed packet (0x83) for sparse rows (< 7 black pixels)""" command = 0x83 row_bytes = row_num.to_bytes(2, 'big') black_count = len(pixel_positions) black_bytes = bytes([0x00, black_count, 0x00]) # Simplified count format repeat_byte = bytes([repeat]) # Pixel positions as 16-bit big-endian values positions_data = b''.join(pos.to_bytes(2, 'big') for pos in pixel_positions) data = row_bytes + black_bytes + repeat_byte + positions_data return build_packet(command, data) # Example: Print empty rows 0-9 for row in range(10): pkt = print_empty_row(row, repeat=1) print(f"Row {row}: {pkt.hex()}") # Example: Print row with pixels at positions 10 and 320 (sparse data) sparse_row = print_bitmap_row_indexed(row_num=3, pixel_positions=[10, 320], repeat=2) print(sparse_row.hex()) ``` -------------------------------- ### Image Data Packets: PrintEmptyRow and PrintBitmapRow Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/interfacing/proto.md Details the commands for sending image data, including PrintEmptyRow for blank rows and PrintBitmapRow for rows with pixel data. Includes explanations of parameters like row number, repeat count, and black pixel count. ```APIDOC ## Image Data Packets ### Description These commands are used to send image data to the printer, either as blank rows or rows containing pixel information. Refer to the [print tasks](print-tasks.md) document for context on how images are printed. ### PrintEmptyRow Command #### Description Fills a specified row with blank (white) pixels. #### Example Packet ``` 55 55 84 03 00 04 02 XX aa aa │ │ └──┤ │ │ │ │ │ │ └─ Checksum │ │ │ └─ Repeat count (repeat row two times) │ │ └─ Row number is 4 │ └─ Data length └─ PrintEmptyRow command ``` ### PrintBitmapRow Command #### Description Sends a row segment containing both black and white pixels. #### Example Packet ``` 55 55 85 0a 00 00 13 00 00 01 ff 00 df 0f XX aa aa │ │ └──┤ └──┴──┤ │ └──┴──┴──┤ │ │ │ │ │ │ │ └─ Checksum │ │ │ │ │ │ │ │ │ │ │ └─ Draw 32 pixels (19 black, 13 empty) │ │ │ │ └─ Repeat count (repeat row 1 time) │ │ │ └─ Black pixel count (19) │ │ └─ Row number is 0 │ └─ Data length └─ PrintBitmapRow command ``` ### Parameters - **Header**: `55 55` (Start of packet) - **Command**: `84` (PrintEmptyRow) or `85` (PrintBitmapRow) - **Data Length**: Variable - **Row Number**: The row to be affected. - **Repeat Count**: How many times to repeat the row. - **Black Pixel Count**: Number of black pixels in the row segment (for PrintBitmapRow). - **Pixel Data**: The actual pixel data (for PrintBitmapRow). - **Checksum**: `XX aa aa` (End of packet) ### Black Pixel Count Segment Details - **Split Mode**: Data is split into chunks, and non-zero bit counts are calculated per chunk. Base chunk size is `printhead size / 8 / 3`. - **Total Mode**: Returns the total number of pixels in little-endian format: `[0, LL, HH]`. - **Auto Mode**: Defaults to split mode; falls back to total mode if split is unavailable. - **Note**: Printers usually function correctly when all 3 bytes of the count are zeros. ``` -------------------------------- ### Export Firmware Data (JavaScript) Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/firmware/header-editor.html Handles the export of firmware data. It creates a Blob from the firmware header and body, generates a download URL, and simulates a click on a hidden anchor element to initiate the file download. The filename is dynamically set. ```javascript exportEl.onclick = () => { const blob = new Blob([fwHeader, fwBody], { type: "application/octet-stream" }); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = downloadUrl; a.download = filename; document.body.appendChild(a); a.click(); URL.revokeObjectURL(downloadUrl); }; ``` -------------------------------- ### Set Page Size Command (Python) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Configures the label dimensions before printing. Supports different formats based on printer model, including 4-byte (rows, columns) and 6-byte (rows, columns, copies) formats. Requires a `build_packet` helper function. ```python def set_page_size_4byte(rows: int, cols: int) -> bytes: """Build SetPageSize packet (4-byte format for B21, B1, etc.)""" command = 0x13 # Convert to big-endian 16-bit values rows_bytes = rows.to_bytes(2, 'big') cols_bytes = cols.to_bytes(2, 'big') data = rows_bytes + cols_bytes return build_packet(command, data) def set_page_size_6byte(rows: int, cols: int, copies: int) -> bytes: """Build SetPageSize packet (6-byte format with copies count)""" command = 0x13 rows_bytes = rows.to_bytes(2, 'big') cols_bytes = cols.to_bytes(2, 'big') copies_bytes = copies.to_bytes(2, 'big') data = rows_bytes + cols_bytes + copies_bytes return build_packet(command, data) # Example: Set 240x384 pixel label (30x48mm at 203 DPI) packet = set_page_size_4byte(rows=240, cols=384) print(packet.hex()) # 55551304 00f0 0180 XX aaaa # Example: 240x384 pixel label, print 2 copies packet = set_page_size_6byte(rows=240, cols=384, copies=2) print(packet.hex()) # 555513060 0f00180 0002 XX aaaa ``` -------------------------------- ### Build NIIMBOT Protocol Packet (Python) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Constructs a binary packet according to the NIIMBOT communication protocol. It includes a header, command, data length, payload, XOR checksum, and tail. This function is essential for sending commands to the printer. ```python def build_packet(command: int, data: bytes) -> bytes: """Build a NIIMBOT protocol packet""" HEAD = bytes([0x55, 0x55]) TAIL = bytes([0xAA, 0xAA]) data_len = len(data) # Calculate XOR checksum (command ^ data_len ^ all_data_bytes) checksum = command ^ data_len for byte in data: checksum ^= byte packet = HEAD + bytes([command, data_len]) + data + bytes([checksum]) + TAIL return packet # Example: Build RFID info request packet # Command 0x1A with data 0x01 rfid_request = build_packet(0x1A, bytes([0x01])) print(rfid_request.hex()) # Output: 55551a01011aaaaa # Example: Set density to level 3 (command 0x21) density_packet = build_packet(0x21, bytes([0x03])) print(density_packet.hex()) # Output: 5555210103aaaa ``` -------------------------------- ### JavaScript Utility Functions for Firmware Editing Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/firmware/header-editor.html Provides essential JavaScript functions for handling firmware data, including number-to-hex conversion, buffer-to-hex formatting, 32-bit unsigned integer to byte array conversion, byte array to 32-bit integer conversion, and array equality checks. ```javascript const numberToHex = (n) => { const hex = n.toString(16); return hex.length === 1 ? `0${hex}` : hex; }; const bufToHex = (buf, separator = " ") => { return Array.from(buf) .map((n) => numberToHex(n)) .join(separator); }; const u32ToBytes = (n) => { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; }; const bytesToI32 = (arr) => { return new DataView(arr.buffer).getInt32(0, true); } const u8ArraysEqual = (a, b) => { return a.length === b.length && a.every((el, i) => el === b[i]); }; ``` -------------------------------- ### NIIMBOT Printer Command Constants and Configuration (Python) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Defines constants for various NIIMBOT printer commands and label types, and provides a function to generate configuration packets. This includes setting print density and label type, crucial for preparing the printer for label jobs. ```python # NIIMBOT Command Constants class Commands: PRINT_START = 0x01 PAGE_START = 0x03 SET_PAGE_SIZE = 0x13 PRINT_QUANTITY = 0x15 PRINT_CLEAR = 0x20 SET_DENSITY = 0x21 SET_LABEL_TYPE = 0x23 SET_AUTO_SHUTDOWN = 0x27 PRINTER_INFO = 0x40 PRINT_BITMAP_ROW_INDEXED = 0x83 PRINT_EMPTY_ROW = 0x84 PRINT_BITMAP_ROW = 0x85 PRINT_STATUS = 0xA3 CONNECT = 0xC1 HEARTBEAT = 0xDC PAGE_END = 0xE3 PRINT_END = 0xF3 # Label Types class LabelType: WITH_GAPS = 1 # Standard die-cut labels BLACK_MARK = 2 # Black mark sensing CONTINUOUS = 3 # Continuous roll PERFORATED = 4 # Perforated labels TRANSPARENT = 5 # Transparent labels # Example: Configure printer settings def configure_printer(density: int = 3, label_type: int = 1): """Returns list of configuration packets""" packets = [] # Set density (1-5 typical range) packets.append(build_packet(Commands.SET_DENSITY, bytes([density]))) # Set label type packets.append(build_packet(Commands.SET_LABEL_TYPE, bytes([label_type]))) return packets ``` -------------------------------- ### Configure Printer Settings (Python) Source: https://context7.com/multimote/niimbot-wiki/llms.txt Configures printer settings like density and label type. It iterates through generated packets and prints their hexadecimal representation. This is typically the first step before sending other commands. ```python for pkt in configure_printer(3, 1): print(pkt.hex()) ``` -------------------------------- ### Implement Minimal Bootloader for AT32F403A Source: https://github.com/multimote/niimbot-wiki/blob/main/docs/hardware/NIIMBOT-B21_C2B/niimbot-b21-c2b-unbrick.md A minimal C bootloader designed to jump execution to the main firmware located at address 0x08002000. It validates the stack pointer before remapping the vector table and transferring control to the application. ```c #include "at32f403a_407.h" #define APP_ADDRESS 0x08002000 typedef void (*pFunction)(void); void jump_to_app(void) { uint32_t appStack = *(__IO uint32_t*)APP_ADDRESS; pFunction appEntry = (pFunction)*(__IO uint32_t*)(APP_ADDRESS + 4); if ((appStack & 0x2FFE0000) == 0x20000000) // Check for valid RAM address { __disable_irq(); SCB->VTOR = APP_ADDRESS; __set_MSP(appStack); __enable_irq(); appEntry(); } } int main(void) { jump_to_app(); while (1) {} } ``` -------------------------------- ### Printer Commands Reference Source: https://context7.com/multimote/niimbot-wiki/llms.txt Lists and describes various commands available for controlling NIIMBOT printers, including print settings, status queries, and configuration. ```APIDOC ## GET /api/commands/reference ### Description Retrieves a reference list of all available NIIMBOT printer commands and their corresponding numerical values. ### Method GET ### Endpoint /api/commands/reference ### Response #### Success Response (200) - **commands** (object) - An object mapping command names to their integer values. - **labelTypes** (object) - An object mapping label type names to their integer values. #### Response Example ```json { "commands": { "PRINT_START": 1, "PAGE_START": 3, "SET_PAGE_SIZE": 19, "PRINT_QUANTITY": 21, "PRINT_CLEAR": 32, "SET_DENSITY": 33, "SET_LABEL_TYPE": 35, "SET_AUTO_SHUTDOWN": 39, "PRINTER_INFO": 64, "PRINT_BITMAP_ROW_INDEXED": 131, "PRINT_EMPTY_ROW": 132, "PRINT_BITMAP_ROW": 133, "PRINT_STATUS": 163, "CONNECT": 193, "HEARTBEAT": 220, "PAGE_END": 227, "PRINT_END": 243 }, "labelTypes": { "WITH_GAPS": 1, "BLACK_MARK": 2, "CONTINUOUS": 3, "PERFORATED": 4, "TRANSPARENT": 5 } } ``` ## POST /api/printer/configure ### Description Configures printer settings such as density and label type. ### Method POST ### Endpoint /api/printer/configure #### Request Body - **density** (integer) - Optional - The print density level (e.g., 1-5). Defaults to 3. - **labelType** (integer) - Optional - The type of label being used (e.g., 1 for WITH_GAPS). Defaults to 1. ### Request Example ```json { "density": 4, "labelType": 2 } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation that the printer settings have been updated. #### Response Example ```json { "message": "Printer configuration updated successfully." } ``` ```