Working tree changes 2024-07-23 00:00
All checks were successful
Test project build / Build (push) Successful in 1m8s

This commit is contained in:
Bot 2024-07-23 00:00:01 +03:00 committed by multimote
parent 70733a64f2
commit a3b3830785
18 changed files with 428 additions and 665 deletions

View File

@ -4,13 +4,14 @@
"type": "module",
"version": "0.0.1",
"scripts": {
"dev-locallib": "yarn install-locallib && yarn dev-open",
"dev-locallib": "yarn install-locallib && yarn sv-check && yarn dev-open",
"dev": "vite --force",
"dev-open": "vite --force --open",
"build": "vite build",
"build-rel": "vite build --base=./",
"preview": "vite preview",
"install-locallib": "yarn --cwd ../niimbluelib && yarn --cwd ../niimbluelib clean-build && yarn add file:../niimbluelib"
"install-locallib": "yarn --cwd ../niimbluelib && yarn --cwd ../niimbluelib clean-build && yarn add file:../niimbluelib",
"sv-check": "svelte-check --tsconfig ./tsconfig.json"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2",
@ -28,6 +29,7 @@
"@types/node": "^20.14.8",
"sass": "^1.77.5",
"svelte": "^4.2.18",
"svelte-check": "^3.8.4",
"tslib": "^2.6.3",
"typescript": "^5.2.2",
"vite": "^5.3.1"

View File

@ -11,7 +11,6 @@
LabelType,
PacketGenerator,
PrintSequenceVariant,
type PrintStatusDecoded,
ResponseCommandId,
PrintError,
} from "@mmote/niimbluelib";

View File

@ -1,9 +1,8 @@
<script lang="ts">
import { PrinterModelId } from "@mmote/niimbluelib";
import { printerClient, connectedPrinterName, connectionState, initClient, heartbeatData } from "../stores";
import { printerClient, connectedPrinterName, connectionState, initClient, heartbeatData, printerConfig } from "../stores";
import type { ConnectionType } from "../types";
import FaIcon from "./FaIcon.svelte";
import { icon } from "@fortawesome/fontawesome-svg-core";
let connectionType: ConnectionType = "bluetooth";
@ -51,7 +50,8 @@
</button>
<div class="dropdown-menu p-1">
<div>
<FaIcon icon="battery-empty"/> {($heartbeatData?.powerLevel ?? 0) * 25}%
Printer info:
<pre>{JSON.stringify($printerConfig, null, 1)}</pre>
</div>
<button class="btn btn-sm btn-primary" on:click={getRfidInfo}>RfidInfo</button>
<button class="btn btn-sm btn-primary" on:click={startHeartbeat}>start heartbeat (test)</button>

View File

@ -11,12 +11,14 @@ import {
Utils,
type HeartbeatData,
type NiimbotAbstractClient,
type PrinterConfig,
} from "@mmote/niimbluelib";
export const connectionState = writable<ConnectionState>("disconnected");
export const connectedPrinterName = writable<string>("");
export const printerClient = writable<NiimbotAbstractClient>();
export const heartbeatData = writable<HeartbeatData>();
export const printerConfig = writable<PrinterConfig>();
export const initClient = (connectionType: ConnectionType) => {
printerClient.update((prevClient: NiimbotAbstractClient) => {
@ -46,21 +48,18 @@ export const initClient = (connectionType: ConnectionType) => {
console.log(`<< ${Utils.bufToHex(e.data)}`);
});
// newClient.addEventListener("packetparsed", (e: PacketParsedEvent) => {
// console.log(e.packet);
// });
newClient.addEventListener("connect", (e: ConnectEvent) => {
console.log("onConnect");
connectionState.set("connected");
connectedPrinterName.set(e.info.deviceName ?? "unknown");
// c.sendPacket(PacketGenerator.setBtSound(false));
printerConfig.set(newClient.getPrinterConfig());
});
newClient.addEventListener("disconnect", () => {
console.log("onDisconnect");
connectionState.set("disconnected");
connectedPrinterName.set("");
printerConfig.set({});
});
newClient.addEventListener("heartbeat", (e: HeartbeatEvent) => {

View File

@ -1,10 +1,10 @@
import type { StartPosition } from "@mmote/niimbluelib";
import type { HeadPosition } from "@mmote/niimbluelib";
export type ConnectionState = "connecting" | "connected" | "disconnected";
export type ConnectionType = "bluetooth" | "serial";
export interface LabelProps {
startPos: StartPosition
startPos: HeadPosition
size: { width: number; height: number }
}
export type LabelPreset = {
@ -12,7 +12,7 @@ export type LabelPreset = {
height: number;
unit: string;
dpmm: number;
startPosition: StartPosition;
startPosition: HeadPosition;
};
export type OjectType = "text" | "rectangle" | "line" | "circle"

View File

@ -7,7 +7,9 @@
"resolveJsonModule": true,
"allowJs": false,
"isolatedModules": true,
"moduleDetection": "force"
"moduleDetection": "force",
"strict": true, /* Enable all strict type-checking options. */
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
}

View File

@ -168,7 +168,7 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24":
"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24":
version "0.3.25"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
@ -336,6 +336,11 @@
dependencies:
undici-types "~5.26.4"
"@types/pug@^2.0.6":
version "2.0.10"
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.10.tgz#52f8dbd6113517aef901db20b4f3fca543b88c1f"
integrity sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==
abab@^2.0.5, abab@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
@ -463,6 +468,11 @@ browser-process-hrtime@^1.0.0:
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
buffer-crc32@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405"
integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==
canvas@^2.8.0:
version "2.11.2"
resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860"
@ -472,7 +482,7 @@ canvas@^2.8.0:
nan "^2.17.0"
simple-get "^3.0.3"
"chokidar@>=3.0.0 <4.0.0":
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
@ -598,6 +608,11 @@ dequal@^2.0.3:
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
detect-indent@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
detect-libc@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
@ -615,6 +630,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
es6-promise@^3.1.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
integrity sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==
esbuild@^0.21.3:
version "0.21.5"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
@ -752,6 +772,11 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
graceful-fs@^4.1.3:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
has-unicode@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@ -890,7 +915,7 @@ locate-character@^3.0.0:
resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-3.0.0.tgz#0305c5b8744f61028ef5d01f444009e00779f974"
integrity sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==
magic-string@^0.30.10, magic-string@^0.30.4:
magic-string@^0.30.10, magic-string@^0.30.4, magic-string@^0.30.5:
version "0.30.10"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
@ -926,6 +951,11 @@ mimic-response@^2.0.0:
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
min-indent@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@ -933,6 +963,11 @@ minimatch@^3.1.1:
dependencies:
brace-expansion "^1.1.7"
minimist@^1.2.0, minimist@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
minipass@^3.0.0:
version "3.3.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
@ -953,11 +988,23 @@ minizlib@^2.1.1:
minipass "^3.0.0"
yallist "^4.0.0"
mkdirp@^0.5.1:
version "0.5.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
dependencies:
minimist "^1.2.6"
mkdirp@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mri@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@ -1093,6 +1140,13 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
rimraf@^2.5.2:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"
rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@ -1125,6 +1179,13 @@ rollup@^4.13.0:
"@rollup/rollup-win32-x64-msvc" "4.18.0"
fsevents "~2.3.2"
sade@^1.7.4:
version "1.8.1"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701"
integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==
dependencies:
mri "^1.1.0"
safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@ -1135,6 +1196,16 @@ safe-buffer@~5.2.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sander@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/sander/-/sander-0.5.1.tgz#741e245e231f07cafb6fdf0f133adfa216a502ad"
integrity sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==
dependencies:
es6-promise "^3.1.2"
graceful-fs "^4.1.3"
mkdirp "^0.5.1"
rimraf "^2.5.2"
sass@^1.77.5:
version "1.77.6"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.6.tgz#898845c1348078c2e6d1b64f9ee06b3f8bd489e4"
@ -1185,6 +1256,16 @@ simple-get@^3.0.3:
once "^1.3.1"
simple-concat "^1.0.0"
sorcery@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/sorcery/-/sorcery-0.11.1.tgz#7cac27ae9c9549b3cd1e4bb85317f7b2dc7b7e22"
integrity sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.14"
buffer-crc32 "^1.0.0"
minimist "^1.2.0"
sander "^0.5.0"
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
@ -1218,11 +1299,41 @@ strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
strip-indent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
dependencies:
min-indent "^1.0.0"
svelte-check@^3.8.4:
version "3.8.4"
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-3.8.4.tgz#7cd51e978e5a289a1278a2ea2ff77d8bd3e2f0c1"
integrity sha512-61aHMkdinWyH8BkkTX9jPLYxYzaAAz/FK/VQqdr2FiCQQ/q04WCwDlpGbHff1GdrMYTmW8chlTFvRWL9k0A8vg==
dependencies:
"@jridgewell/trace-mapping" "^0.3.17"
chokidar "^3.4.1"
picocolors "^1.0.0"
sade "^1.7.4"
svelte-preprocess "^5.1.3"
typescript "^5.0.3"
svelte-hmr@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.16.0.tgz#9f345b7d1c1662f1613747ed7e82507e376c1716"
integrity sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==
svelte-preprocess@^5.1.3:
version "5.1.4"
resolved "https://registry.yarnpkg.com/svelte-preprocess/-/svelte-preprocess-5.1.4.tgz#14ada075c94bbd2b71c5ec70ff72f8ebe1c95b91"
integrity sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==
dependencies:
"@types/pug" "^2.0.6"
detect-indent "^6.1.0"
magic-string "^0.30.5"
sorcery "^0.11.0"
strip-indent "^3.0.0"
svelte@^4.2.18:
version "4.2.18"
resolved "https://registry.yarnpkg.com/svelte/-/svelte-4.2.18.tgz#33dbce74e83eb6dcc54dbea25f9758b1d8e8bb78"
@ -1299,6 +1410,11 @@ typescript-event-target@^1.1.1:
resolved "https://registry.yarnpkg.com/typescript-event-target/-/typescript-event-target-1.1.1.tgz#20a6d491b77d2e37dc432c5394ab74c0d7065539"
integrity sha512-dFSOFBKV6uwaloBCCUhxlD3Pr/P1a/tJdcmPrTXCHlEFD3faj0mztjcGn6VBAhQ0/Bdy8K3VWrrqwbt/ffsYsg==
typescript@^5.0.3:
version "5.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa"
integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==
typescript@^5.2.2:
version "5.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507"

View File

@ -1,6 +1,6 @@
import { Mutex } from "async-mutex";
import { ConnectionInfo, NiimbotAbstractClient } from ".";
import { NiimbotPacket, PacketParser, ResponseCommandId } from "../packets";
import { NiimbotPacket, ResponseCommandId } from "../packets";
import { Utils } from "../utils";
import {
ConnectEvent,
@ -40,7 +40,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient {
const disconnectListener = async () => {
this.gattServer = undefined;
this.channel = undefined;
this.config = {};
this.printerConfig = {};
this.stopHeartbeat();
this.dispatchTypedEvent("disconnect", new DisconnectEvent());
device.removeEventListener("gattserverdisconnected", disconnectListener);
@ -81,8 +81,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient {
};
try {
const data = await this.fetchPrinterConfig();
console.log(data);
await this.fetchPrinterConfig();
} catch (e) {
console.error(e);
}
@ -101,7 +100,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient {
this.gattServer?.disconnect();
this.gattServer = undefined;
this.channel = undefined;
this.config = {};
this.printerConfig = {};
}
/**
@ -112,7 +111,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient {
return this.mutex.runExclusive(async () => {
await this.sendPacket(packet, true);
if (packet.isNoResponse()) {
if (packet.isOneWay()) {
return new NiimbotPacket(-1, []); // or undefined is better?
}

View File

@ -1,5 +1,5 @@
import { ConnectionInfo } from ".";
import { HeartbeatData, NiimbotPacket, ParsedPacket } from "../packets";
import { HeartbeatData, NiimbotPacket } from "../packets";
/**
@ -22,17 +22,6 @@ export class DisconnectEvent extends Event {
}
} // add reason maybe?
/**
*
*/
// export class PacketParsedEvent extends Event {
// packet: ParsedPacket;
// constructor(packet: ParsedPacket) {
// super("packetparsed");
// this.packet = packet;
// }
// }
/**
*
*/

View File

@ -1,7 +1,7 @@
import { NiimbotPacket, PrinterModelId } from "../packets";
import { AutoShutdownTime, BatteryChargeLevel, NiimbotPacket, PrinterModelId } from "../packets";
import { TypedEventTarget } from "typescript-event-target";
import { ClientEventMap, HeartbeatEvent } from "./events";
import { Abstraction } from "../packets/parser/abstraction";
import { Abstraction } from "../packets/abstraction";
export type ConnectionInfo = {
deviceName?: string;
@ -9,11 +9,15 @@ export type ConnectionInfo = {
export interface PrinterConfig {
model?: PrinterModelId;
serial?: string;
mac?: string;
charge?: BatteryChargeLevel;
autoShutdownTime?: AutoShutdownTime;
}
export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEventMap> {
public readonly abstraction: Abstraction;
protected config: PrinterConfig = {};
protected printerConfig: PrinterConfig = {};
private heartbeatTimer?: NodeJS.Timeout;
constructor() {
@ -47,26 +51,18 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent
await this.sendRaw(packet.toBytes(), force);
}
// todo: delete
// public async sendPacketWaitResponseParsed(packet: NiimbotPacket, timeoutMs?: number): Promise<ParsedPacket> {
// const response: NiimbotPacket = await this.sendPacketWaitResponse(packet, timeoutMs);
// // todo: prevent double parsing without duplicating sendPacketWaitResponse
// const data = PacketParser.parse(response);
// if (!data) {
// throw new Error("Decoder for this packet is not implemented or packet is invalid");
// }
// return data;
// }
public async fetchPrinterConfig(): Promise<PrinterConfig> {
const props: PrinterConfig = {};
props.model = await this.abstraction.getPrinterModel();
return props;
this.printerConfig = {};
this.printerConfig.model = await this.abstraction.getPrinterModel();
this.printerConfig.serial = await this.abstraction.getPrinterSerialNumber();
this.printerConfig.mac = await this.abstraction.getPrinterBluetoothMacAddress();
this.printerConfig.charge = await this.abstraction.getBatteryChargeLevel();
this.printerConfig.autoShutdownTime = await this.abstraction.getAutoShutDownTime();
return this.printerConfig;
}
public getConfig(): PrinterConfig {
return this.config;
public getPrinterConfig(): PrinterConfig {
return this.printerConfig;
}
/**

View File

@ -1,5 +1,7 @@
import {
HeartbeatType as HeartbeatType,
AutoShutdownTime,
BatteryChargeLevel,
HeartbeatType,
LabelType,
NiimbotPacket,
PacketGenerator,
@ -8,37 +10,9 @@ import {
ResponseCommandId,
SoundSettingsItemType,
SoundSettingsType,
} from "..";
import { NiimbotAbstractClient, Utils, Validators } from "../..";
import { SequentialDataReader } from "../parser/data_reader";
// ---------------------------------------------------------
// experiments
// export abstract class ParsedPacket2 {
// public readonly commandId: ResponseCommandId;
// constructor(commandId: ResponseCommandId) {
// this.commandId = commandId;
// }
// public abstract parse(packet: NiimbotPacket): ParsedPacket2;
// }
// export class PrintErrorDecoded2 extends ParsedPacket2 {
// public errorType: number;
// constructor() {
// super(ResponseCommandId.In_PrintError);
// this.errorType = 0;
// }
// public parse(packet: NiimbotPacket): PrintErrorDecoded2 {
// Validators.u8ArrayLengthEqual(packet.getData(), 1);
// const p = new PrintErrorDecoded2();
// p.errorType = packet.getData()[0];
// return p;
// }
// }
// ---------------------------------------------------------
} from ".";
import { NiimbotAbstractClient, Utils, Validators } from "..";
import { SequentialDataReader } from "./data_reader";
export class PrintError extends Error {
public readonly reasonId: number;
@ -72,11 +46,17 @@ export interface RfidInfo {
export interface HeartbeatData {
paperState: number;
rfidReadState: number;
closingState: number;
lidState: number;
powerLevel: number;
}
/** Experimental class for retrieving data. Not sure for name. */
export interface SoundSettings {
category: SoundSettingsType;
item: SoundSettingsItemType;
value: boolean;
}
/** Not sure for name. */
export class Abstraction {
private client: NiimbotAbstractClient;
private timeout: number = 1000;
@ -93,6 +73,7 @@ export class Abstraction {
this.timeout = value;
}
/** Send packet and wait for response */
private async send(packet: NiimbotPacket): Promise<NiimbotPacket> {
return this.client.sendPacketWaitResponse(packet, this.timeout);
}
@ -102,10 +83,7 @@ export class Abstraction {
if (packet.getCommand() === ResponseCommandId.In_PrintError) {
Validators.u8ArrayLengthEquals(packet.getData(), 1);
throw new PrintError(
`Print error (${ResponseCommandId[packet.getCommand()]} packet received)`,
packet.getData()[0]
);
throw new PrintError(`Print error (${ResponseCommandId[packet.getCommand()]} packet received)`, packet.getData()[0]);
}
Validators.u8ArrayLengthAtLeast(packet.getData(), 4); // can be 8, 10, but ignore it for now
@ -173,50 +151,36 @@ export class Abstraction {
const info: HeartbeatData = {
paperState: -1,
rfidReadState: -1,
closingState: -1,
lidState: -1,
powerLevel: -1,
};
// originally expected packet length is calculated from model id, but we make it simple
// originally expected packet length is bound to model id, but we make it more robust and simple
const len = packet.getData().length;
const r = new SequentialDataReader(packet.getData());
if (len === 17 - 7) {
if (len === 10) {
// d110
// n3 = n8 + 9;
// DataCheck.parseClosingState(callback, byArray[n3], n2);
// DataCheck.parsePowerLevel(callback, byArray[n8 + 10]);
// DataCheck.parseRfidReadState(callback, byArray[n3], n2); ??????
r.skip(8);
info.closingState = r.readI8();
info.lidState = r.readI8();
info.powerLevel = r.readI8();
} else if (len === 27 - 7) {
// 19 parsePaperState
// 20 parseRfidReadState
} else if (len === 20) {
r.skip(18);
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
} else if (len === 26 - 7) {
// 16 parseClosingState
// 17 parsePowerLevel
// 18 parsePaperState
// 19 parseRfidReadState
} else if (len === 19) {
r.skip(15);
info.closingState = r.readI8();
info.lidState = r.readI8();
info.powerLevel = r.readI8();
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
} else if (len === 20 - 7) {
} else if (len === 13) {
// b1
r.skip(9);
info.closingState = r.readI8();
info.lidState = r.readI8();
info.powerLevel = r.readI8();
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
// 10 parseClosingState
// 11 parsePowerLevel
// 12 parsePaperState
// 13 parseRfidReadState
} else {
throw new Error("Invalid heartbeat length");
}
@ -224,4 +188,45 @@ export class Abstraction {
return info;
}
public async getBatteryChargeLevel(): Promise<BatteryChargeLevel> {
const packet = await this.send(PacketGenerator.getPrinterInfo(PrinterInfoType.BatteryChargeLevel));
Validators.u8ArrayLengthEquals(packet.getData(), 1);
return packet.getData()[0] as BatteryChargeLevel;
}
public async getAutoShutDownTime(): Promise<AutoShutdownTime> {
const packet = await this.send(PacketGenerator.getPrinterInfo(PrinterInfoType.AutoShutdownTime));
Validators.u8ArrayLengthEquals(packet.getData(), 1);
return packet.getData()[0] as AutoShutdownTime;
}
public async getLabelType(): Promise<LabelType> {
const packet = await this.send(PacketGenerator.getPrinterInfo(PrinterInfoType.LabelType));
Validators.u8ArrayLengthEquals(packet.getData(), 1);
return packet.getData()[0] as LabelType;
}
public async getPrinterSerialNumber(): Promise<string> {
const packet = await this.send(PacketGenerator.getPrinterInfo(PrinterInfoType.SerialNumber));
Validators.u8ArrayLengthAtLeast(packet.getData(), 1);
return Utils.u8ArrayToString(packet.getData());
}
public async getPrinterBluetoothMacAddress(): Promise<string> {
const packet = await this.send(PacketGenerator.getPrinterInfo(PrinterInfoType.BluetoothAddress));
Validators.u8ArrayLengthAtLeast(packet.getData(), 1);
return Utils.bufToHex(packet.getData().reverse(), ":");
}
public async isSoundEnabled(soundType: SoundSettingsItemType): Promise<boolean> {
const packet = await this.send(PacketGenerator.getSoundSettings(soundType));
Validators.u8ArrayLengthEquals(packet.getData(), 3);
const value = !!packet.getData()[2];
return value;
}
public async setSoundEnabled(soundType: SoundSettingsItemType, value: boolean): Promise<void> {
await this.send(PacketGenerator.setSoundSettings(soundType, value));
}
}

View File

@ -1,4 +1,4 @@
import { Utils } from "../..";
import { Utils } from "..";
/** Utility class to sequentially fetch data from byte array. EOF checks included. */
export class SequentialDataReader {

View File

@ -1,4 +1,194 @@
export * from "./types";
export * from "./parser";
export enum RequestCommandId {
/** see {@link AutoShutdownTime} */
CancelPrint = 0xda,
Heartbeat = 0xdc,
LabelPositioningCalibration = 0x8e, //-114,
PageEnd = 0xe3,
PageNumber = 0x05,
PageStart = 0x03,
PrintBitmapRow = 0x85, // -123
PrintBitmapRowIndexed = 0x83, // -125, indexed if black pixels < 6
PrintClear = 0x20,
PrintEmptyRow = 0x84, // -124
PrintEnd = 0xf3,
PrinterInfo = 0x40, // See PrinterInfoType
PrinterStatusData = 0xa5,
PrintQuantity = 0x15,
PrintStart = 0x01,
PrintStartV3 = 0x02,
PrintStatus = 0xa3,
RfidInfo = 0x1a,
RfidInfo2 = 0x1c,
RfidSuccessTimes = 0x54,
SetAutoShutdownTime = 0x27, ///
SetDensity = 0x21,
SetLabelType = 0x23 /* D11 - 1,5, for D110 able to set 1,2,3,5; see LabelType */,
SetPageSize = 0x13, // 2, 4 or 6 bytes
SoundSettings = 0x58,
Unknown1 = 0x0b, // some info request (niimbot app), 01 long 02 short
WriteRFID = 0x70,
}
export enum ResponseCommandId {
In_Error = 0x00,
In_Heartbeat1 = 0xdd,
In_Heartbeat2 = 0xdf,
In_Heartbeat3 = 0xde,
In_Heartbeat4 = 0xd9,
In_PageEnd = 0xe3,
In_PageStart = 0x04,
In_PrintClear = 0x30,
In_PrintEmptyRows = 0xd3,
In_PrintEnd = 0xf4,
In_PrinterInfoAutoShutDownTime = 0x47,
In_PrinterInfoBluetoothAddress = 0x4d,
In_PrinterInfoDensity = 0x41,
In_PrinterInfoElectricity = 0x4a,
In_PrinterInfoHardWareVersion = 0x4c,
In_PrinterInfoLabelType = 0x43,
In_PrinterInfoPrinterCode = 0x48,
In_PrinterInfoSerialNumber = 0x4b,
In_PrinterInfoSoftWareVersion = 0x49,
In_PrinterInfoUnknown1 = 0x4f,
IN_PrinterStatusData = 0xb5,
In_PrintStatus = 0xb3,
In_PrintError = 0xdb, // For example, sent on SetPageSize when page print is not started
In_PrintQuantity = 0x16,
In_PrintStart = 0x02,
In_RfidInfo = 0x1b,
IN_RfidSuccessTimes = 0x64,
In_SetAutoShutdownTime = 0x37,
In_SetDensity = 0x31,
In_SetLabelType = 0x33,
In_SetPageSize = 0x14,
In_SoundSettings = 0x68,
In_Unknown1 = 0xe4,
In_Unknown2 = 0xc2,
}
export enum PrinterInfoType {
Density = 1,
Speed = 2,
LabelType = 3,
Language = 6,
AutoShutdownTime = 7,
/** See {@link PrinterId} */
PrinterModelId = 8,
SoftWareVersion = 9,
BatteryChargeLevel = 10,
SerialNumber = 11,
HardWareVersion = 12,
BluetoothAddress = 13,
PrintMode = 14,
Unknown1 = 15,
}
export enum SoundSettingsType {
SetSound = 0x01,
GetSoundState = 0x02,
}
export enum SoundSettingsItemType {
BluetoothConnectionSound = 0x01,
PowerSound = 0x02,
}
// https://github.com/dadrum/niimbot_flutter_plugin/blob/main/lib/niimbot/niimbot_platform_interface/niimbot.dart#L167
export enum LabelType {
Invalid = 0,
/** Default for D11 and similar */
Separated = 1,
WithBlackMarkers = 2,
Continuous = 3,
Perforated = 4,
Transparent = 5,
}
export enum HeartbeatType {
Unknown1 = 1,
Unknown2 = 2,
Unknown3 = 3,
Unknown4 = 4,
}
export enum AutoShutdownTime {
Shutdown15min = 1,
Shutdown30min = 2,
Shutdown45min = 3,
Shutdown60min = 4,
}
/** Battery charge level */
export enum BatteryChargeLevel {
Charge0 = 0,
Charge25 = 1,
Charge50 = 2,
Charge75 = 3,
Charge100 = 4,
}
/** Generated from android app (assets/flutter_assets/assets/config/printerList.json) */
export enum PrinterModelId {
UNKNOWN = 0,
T6 = 51715,
TP2M_H = 4609,
B31 = 5632,
B1 = 4096,
M2_H = 4608,
B21_PRO = 785,
P1 = 1024,
T2S = 53250,
B50W = 51714,
T7 = 51717,
B50 = 51713,
Z401 = 2051,
B32R = 2050,
A63 = 2054,
T8S = 2053,
B32 = 2049,
B18S = 3585,
B18 = 3584,
MP3K_W = 4867,
MP3K = 4866,
K3_W = 4865,
K3 = 4864,
B3S_P = 272,
S6 = 261,
B3S = 256,
B3S_V2 = 260,
B3S_V3 = 262,
B3 = 52993,
A203 = 2818,
A20 = 2817,
B203 = 2816,
S1 = 51458,
JC_M90 = 51461,
S3 = 51460,
B11 = 51457,
B21_H = 784,
B21S_C2B = 776,
B21S = 777,
B21_L2B = 769,
B21_C2B = 771,
B21_C2B_V2 = 775,
B21 = 768,
B16 = 1792,
BETTY = 2561,
D101 = 2560,
D110_M = 2320,
HI_D110 = 2305,
D110 = 2304,
D11_H = 528,
D11S = 514,
FUST = 513,
D11 = 512,
ET10 = 5376,
P18 = 1026,
P1S = 1025,
T8 = 51718,
}
export * from "./packet";
export * from "./packet_generator";
export * from "./abstraction";
export * from "./data_reader";

View File

@ -1,5 +1,5 @@
import { Validators } from "../utils";
import { RequestCommandId, ResponseCommandId } from "./types";
import { RequestCommandId, ResponseCommandId } from ".";
export class NiimbotPacket {
public static readonly HEAD = new Uint8Array([0x55, 0x55]);
@ -10,21 +10,21 @@ export class NiimbotPacket {
private validResponseIds: ResponseCommandId[];
/** There can be no response after this request. */
private noResponse: boolean;
private oneWay: boolean;
constructor(commandId: number, data: Uint8Array | number[], validResponseIds: ResponseCommandId[] = []) {
this.commandId = commandId;
this.data = data instanceof Uint8Array ? data : new Uint8Array(data);
this.validResponseIds = validResponseIds;
this.noResponse = false;
this.oneWay = false;
}
public setNoResponse(): void {
this.noResponse = true;
this.oneWay = true;
}
public isNoResponse(): boolean {
return this.noResponse;
public isOneWay(): boolean {
return this.oneWay;
}
public getValidResponseIds(): ResponseCommandId[] {

View File

@ -64,34 +64,19 @@ export class PacketGenerator {
);
}
public static setBtSound(on: boolean): NiimbotPacket {
public static setSoundSettings(soundType: SoundSettingsItemType, on: boolean): NiimbotPacket {
return new NiimbotPacket(
RequestCommandId.SoundSettings,
[SoundSettingsType.SetSound, SoundSettingsItemType.BluetoothConnectionSound, on ? 1 : 0],
[SoundSettingsType.SetSound, soundType, on ? 1 : 0],
[ResponseCommandId.In_SoundSettings]
);
}
public static getBtSoundEnabled(): NiimbotPacket {
return new NiimbotPacket(
RequestCommandId.SoundSettings,
[SoundSettingsType.GetSoundState, SoundSettingsItemType.BluetoothConnectionSound, 1],
[ResponseCommandId.In_SoundSettings]
);
}
public static setPowerSound(on: boolean): NiimbotPacket {
public static getSoundSettings(soundType: SoundSettingsItemType): NiimbotPacket {
return new NiimbotPacket(
RequestCommandId.SoundSettings,
[SoundSettingsType.SetSound, SoundSettingsItemType.PowerSound, on ? 1 : 0],
[ResponseCommandId.In_SoundSettings]
);
}
public static getPowerSoundEnabled(): NiimbotPacket {
return new NiimbotPacket(
RequestCommandId.SoundSettings,
[SoundSettingsType.GetSoundState, SoundSettingsItemType.PowerSound, 1],
[SoundSettingsType.GetSoundState, soundType, 1],
[ResponseCommandId.In_SoundSettings]
);
}

View File

@ -1,3 +0,0 @@
export * from "./data_reader"
export * from "./parsed_packets"
export * from "./abstraction"

View File

@ -1,327 +0,0 @@
// todo: migrate to Abstraction class
import { LabelType, NiimbotPacket, ResponseCommandId, SoundSettingsItemType, SoundSettingsType } from "..";
import { Utils, Validators } from "../..";
import { SequentialDataReader } from "../parser/data_reader";
export interface ParsedPacket {
commandId: ResponseCommandId;
}
export interface PrintErrorDecoded extends ParsedPacket {
/**
* 8 - no paper?
*/
errorType: number;
}
export interface SettingsInDecoded extends ParsedPacket {
category: SoundSettingsType;
item: SoundSettingsItemType;
value: boolean;
}
export interface PrinterInfoSerialDecoded extends ParsedPacket {
// infoType: PrinterInfoType
serialNumber: string;
}
export interface PrinterInfoLabelTypeDecoded extends ParsedPacket {
labelType: number;
}
export interface RfidInfoDecoded extends ParsedPacket {
tagPresent: boolean;
uuid: string;
barCode: string;
serialNumber: string;
allPaper: number;
usedPaper: number;
consumablesType: LabelType;
}
export interface PrinterInfoPrinterModelIdDecoded extends ParsedPacket {
/** See {@link PrinterId} */
model: number;
}
export interface PrintStatusDecoded extends ParsedPacket {
/** 0 n */
page: number;
/** 0 100 */
pagePrintProgress: number;
/** 0 100 */
pageFeedProgress: number;
error?: number
}
/** closingState inverted on some printers */
export interface HeartbeatDecoded extends ParsedPacket {
paperState: number;
rfidReadState: number;
closingState: number;
powerLevel: number;
}
export class PacketParser {
private static decodePrinterInfoSerial(packet: NiimbotPacket): PrinterInfoSerialDecoded {
return {
commandId: packet.getCommand(),
serialNumber: Utils.u8ArrayToString(packet.getData()),
};
}
private static decodeSettings(packet: NiimbotPacket): SettingsInDecoded {
Validators.u8ArrayLengthEquals(packet.getData(), 3);
return {
commandId: packet.getCommand(),
category: packet.getData()[0],
item: packet.getData()[1],
value: !!packet.getData()[2],
};
}
private static decodePrinterInfoLabelType(packet: NiimbotPacket): PrinterInfoLabelTypeDecoded {
Validators.u8ArrayLengthEquals(packet.getData(), 1);
return {
commandId: packet.getCommand(),
labelType: packet.getData()[0],
};
}
private static decodePrinterInfoPrinterModelId(packet: NiimbotPacket): PrinterInfoPrinterModelIdDecoded {
Validators.u8ArrayLengthEquals(packet.getData(), 2);
return {
commandId: packet.getCommand(),
model: Utils.bytesToI16(packet.getData()),
};
}
// 55 55 1b 27 -- 88 1d ab 43 d3 8c 00 00 -- 08 - 30 32 32 38 32 32 38 30 -- 10 - 50 5a 31 47 33 31 31 33 33 30 30 30 30 33 38 35 -- 00 fc -- 00 38 -- 01 -- b2 aa aa
private static decodeRfidInfo(packet: NiimbotPacket): RfidInfoDecoded {
const info: RfidInfoDecoded = {
commandId: packet.getCommand(),
tagPresent: false,
uuid: "",
barCode: "",
serialNumber: "",
allPaper: -1,
usedPaper: -1,
consumablesType: LabelType.Invalid,
};
if (packet.getData().length === 1) {
return info;
}
const r = new SequentialDataReader(packet.getData());
info.tagPresent = true;
info.uuid = Utils.bufToHex(r.readBytes(8), "");
info.barCode = r.readVString();
info.serialNumber = r.readVString();
info.allPaper = r.readI16();
info.usedPaper = r.readI16();
info.consumablesType = r.readI8() as LabelType;
r.end();
return info;
}
// 55 55 dd 0a 10 23 00 69 00 69 32 4f 01 04 9c aa aa
// 55 55 dd 0a 10 23 00 52 00 52 32 4f 00 04 9d aa aa
private static decodeHeartbeat(packet: NiimbotPacket): HeartbeatDecoded {
const info: HeartbeatDecoded = {
commandId: packet.getCommand(),
paperState: -1,
rfidReadState: -1,
closingState: -1,
powerLevel: -1,
};
// originally expected packet length is calculated from model id, but we make it simple
const len = packet.getData().length;
const r = new SequentialDataReader(packet.getData());
if (len === 17 - 7) {
// d110
// n3 = n8 + 9;
// DataCheck.parseClosingState(callback, byArray[n3], n2);
// DataCheck.parsePowerLevel(callback, byArray[n8 + 10]);
// DataCheck.parseRfidReadState(callback, byArray[n3], n2); ??????
r.skip(8);
info.closingState = r.readI8();
info.powerLevel = r.readI8();
} else if (len === 27 - 7) {
// 19 parsePaperState
// 20 parseRfidReadState
r.skip(18);
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
} else if (len === 26 - 7) {
// 16 parseClosingState
// 17 parsePowerLevel
// 18 parsePaperState
// 19 parseRfidReadState
r.skip(15);
info.closingState = r.readI8();
info.powerLevel = r.readI8();
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
} else if (len === 20 - 7) {
// b1
r.skip(9);
info.closingState = r.readI8();
info.powerLevel = r.readI8();
info.paperState = r.readI8();
info.rfidReadState = r.readI8();
// 10 parseClosingState
// 11 parsePowerLevel
// 12 parsePaperState
// 13 parseRfidReadState
} else {
throw new Error("Invalid heartbeat length");
}
r.end();
return info;
}
/*
d110, 3 pages
5555 b3 04 00000000 b7aaaa
5555 b3 04 00000000 b7aaaa
5555 b3 04 00000000 b7aaaa
5555 b3 04 00001000 a7aaaa
5555 b3 04 00002100 96aaaa
5555 b3 04 00002100 96aaaa
5555 b3 04 00004200 f5aaaa
5555 b3 04 00005300 e4aaaa
5555 b3 04 00006400 d3aaaa
5555 b3 04 00006419 caaaaa
5555 b3 04 00006432 e1aaaa
5555 b3 04 0000644d 9eaaaa
5555 b3 04 00010000 b6aaaa
5555 b3 04 00010000 b6aaaa
5555 b3 04 00010000 b6aaaa
5555 b3 04 00012100 97aaaa
5555 b3 04 00012100 97aaaa
5555 b3 04 00012100 97aaaa
5555 b3 04 00014200 f4aaaa
5555 b3 04 00015300 e5aaaa
5555 b3 04 00016404 d6aaaa
5555 b3 04 00016420 f2aaaa
5555 b3 04 0001643f edaaaa
5555 b3 04 00016460 b2aaaa
5555 b3 04 00020000 b5aaaa
5555 b3 04 00020000 b5aaaa
5555 b3 04 00020000 b5aaaa
5555 b3 04 00022100 94aaaa
5555 b3 04 00022100 94aaaa
5555 b3 04 00023200 87aaaa
5555 b3 04 00025300 e6aaaa
5555 b3 04 00025300 e6aaaa
5555 b3 04 00026422 f3aaaa
5555 b3 04 00026446 97aaaa
5555 b3 04 00036464 b4aaaa
b3, 3 pages
5555 b3 0a 0000 0000031f00000000 a5aaaa
5555 b3 0a 0000 0000031a00000000 a0aaaa
5555 b3 0a 0000 0000031900010000 a2aaaa
5555 b3 0a 0000 0000031900010000 a2aaaa
5555 b3 0a 0000 0000031900010000 a2aaaa
5555 b3 0a 0000 0c00031900010000 aeaaaa
5555 b3 0a 0000 1d00031900010000 bfaaaa
5555 b3 0a 0000 2e00031900010000 8caaaa
5555 b3 0a 0000 4200031900010000 e0aaaa
5555 b3 0a 0000 5600031900010000 f4aaaa
5555 b3 0a 0000 642c031900010000 eaaaaa
5555 b3 0a 0001 0a00031900010000 a9aaaa
5555 b3 0a 0001 1e00031900010000 bdaaaa
5555 b3 0a 0001 2f00031900010000 8caaaa
5555 b3 0a 0001 4600031900010000 e5aaaa
5555 b3 0a 0001 5500031900010000 f6aaaa
5555 b3 0a 0001 6400031900010000 c7aaaa
5555 b3 0a 0001 6403031900010000 c4aaaa
5555 b3 0a 0001 640c031900010000 cbaaaa
5555 b3 0a 0001 6435031900010000 f2aaaa
5555 b3 0a 0001 6463031900010000 a4aaaa
5555 b3 0a 0002 1200031900010000 b2aaaa
5555 b3 0a 0002 2600031b00010000 84aaaa
5555 b3 0a 0002 3800031b00010000 9aaaaa
5555 b3 0a 0002 4b00031d00010000 efaaaa
5555 b3 0a 0002 5d00031e00010000 faaaaa
5555 b3 0a 0002 6401031e00010000 c2aaaa
5555 b3 0a 0002 6405031e00010000 c6aaaa
5555 b3 0a 0002 642f031e00010000 ecaaaa
5555 b3 0a 0002 6451031e00010000 92aaaa
5555 b3 0a 0003 6464031e00010000 a6aaaa
*/
private static decodePrintStatus(packet: NiimbotPacket): PrintStatusDecoded {
Validators.u8ArrayLengthAtLeast(packet.getData(), 4); // can be 8, 10, but ignore it for now
const result: PrintStatusDecoded = {
commandId: packet.getCommand(),
page: -1,
pagePrintProgress: -1,
pageFeedProgress: -1,
};
const r = new SequentialDataReader(packet.getData());
result.page = r.readI16();
result.pagePrintProgress = r.readI8();
result.pageFeedProgress = r.readI8();
if(packet.getData().length === 10) {
r.skip(2)
result.error = r.readI8();
}
return result;
}
private static decodePrintError(packet: NiimbotPacket): PrintErrorDecoded {
Validators.u8ArrayLengthEquals(packet.getData(), 1);
return {
commandId: packet.getCommand(),
errorType: packet.getData()[0]
};
}
public static parse(packet: NiimbotPacket): ParsedPacket | undefined {
const command: ResponseCommandId = packet.getCommand();
switch (command) {
case ResponseCommandId.In_SoundSettings:
return this.decodeSettings(packet);
case ResponseCommandId.In_PrinterInfoSerialNumber:
return this.decodePrinterInfoSerial(packet);
case ResponseCommandId.In_PrinterInfoLabelType:
return this.decodePrinterInfoLabelType(packet);
case ResponseCommandId.In_RfidInfo:
return this.decodeRfidInfo(packet);
case ResponseCommandId.In_PrinterInfoPrinterCode:
return this.decodePrinterInfoPrinterModelId(packet);
case ResponseCommandId.In_Heartbeat1:
return this.decodeHeartbeat(packet);
case ResponseCommandId.In_PrintError:
return this.decodePrintError(packet);
case ResponseCommandId.In_PrintStatus:
return this.decodePrintStatus(packet);
}
return undefined;
}
}

View File

@ -1,189 +0,0 @@
export enum RequestCommandId {
/** see {@link AutoShutdownTime} */
CancelPrint = 0xda,
Heartbeat = 0xdc,
LabelPositioningCalibration = 0x8e, //-114,
PageEnd = 0xe3,
PageNumber = 0x05,
PageStart = 0x03,
PrintBitmapRow = 0x85, // -123
PrintBitmapRowIndexed = 0x83, // -125, indexed if black pixels < 6
PrintClear = 0x20,
PrintEmptyRow = 0x84, // -124
PrintEnd = 0xf3,
PrinterInfo = 0x40, // See PrinterInfoType
PrinterStatusData = 0xa5,
PrintQuantity = 0x15,
PrintStart = 0x01,
PrintStartV3 = 0x02,
PrintStatus = 0xa3,
RfidInfo = 0x1a,
RfidInfo2 = 0x1c,
RfidSuccessTimes = 0x54,
SetAutoShutdownTime = 0x27, ///
SetDensity = 0x21,
SetLabelType = 0x23 /* D11 - 1,5, for D110 able to set 1,2,3,5; see LabelType */,
SetPageSize = 0x13, // 2, 4 or 6 bytes
SoundSettings = 0x58,
Unknown1 = 0x0b, // some info request (niimbot app), 01 long 02 short
WriteRFID = 0x70,
}
export enum ResponseCommandId {
In_Error = 0x00,
In_Heartbeat1 = 0xdd,
In_Heartbeat2 = 0xdf,
In_Heartbeat3 = 0xde,
In_Heartbeat4 = 0xd9,
In_PageEnd = 0xe3,
In_PageStart = 0x04,
In_PrintClear = 0x30,
In_PrintEmptyRows = 0xd3,
In_PrintEnd = 0xf4,
In_PrinterInfoAutoShutDownTime = 0x47,
In_PrinterInfoBluetoothAddress = 0x4d,
In_PrinterInfoDensity = 0x41,
In_PrinterInfoElectricity = 0x4a,
In_PrinterInfoHardWareVersion = 0x4c,
In_PrinterInfoLabelType = 0x43,
In_PrinterInfoPrinterCode = 0x48,
In_PrinterInfoSerialNumber = 0x4b,
In_PrinterInfoSoftWareVersion = 0x49,
In_PrinterInfoUnknown1 = 0x4f,
IN_PrinterStatusData = 0xb5,
In_PrintStatus = 0xb3,
In_PrintError = 0xdb, // For example, sent on SetPageSize when page print is not started
In_PrintQuantity = 0x16,
In_PrintStart = 0x02,
In_RfidInfo = 0x1b,
IN_RfidSuccessTimes = 0x64,
In_SetAutoShutdownTime = 0x37,
In_SetDensity = 0x31,
In_SetLabelType = 0x33,
In_SetPageSize = 0x14,
In_SoundSettings = 0x68,
In_Unknown1 = 0xe4,
In_Unknown2 = 0xc2,
}
export enum PrinterInfoType {
Density = 1,
Speed = 2,
LabelType = 3,
Language = 6,
AutoShutDownTime = 7,
/** See {@link PrinterId} */
PrinterModelId = 8,
SoftWareVersion = 9,
Electricity = 10,
SerialNumber = 11,
HardWareVersion = 12,
BluetoothAddress = 13,
PrintMode = 14,
Unknown1 = 15,
}
export enum SoundSettingsType {
SetSound = 0x01,
GetSoundState = 0x02,
}
export enum SoundSettingsItemType {
BluetoothConnectionSound = 0x01,
PowerSound = 0x02,
}
// https://github.com/dadrum/niimbot_flutter_plugin/blob/main/lib/niimbot/niimbot_platform_interface/niimbot.dart#L167
export enum LabelType {
Invalid = 0,
/** Default for D11 and similar */
Separated = 1,
WithBlackMarkers = 2,
Continuous = 3,
Perforated = 4,
Transparent = 5,
}
export enum HeartbeatType {
Unknown1 = 1,
Unknown2 = 2,
Unknown3 = 3,
Unknown4 = 4,
}
export enum AutoShutdownTime {
Shutdown15min = 1,
Shutdown30min = 2,
Shutdown45min = 3,
Shutdown60min = 4,
}
/** Battery charge level */
export enum PowerLevel {
Power0 = 0,
Power25 = 1,
Power50 = 2,
Power75 = 3,
Power100 = 4,
}
/** Generated from android app (assets/flutter_assets/assets/config/printerList.json) */
export enum PrinterModelId {
UNKNOWN = 0,
T6 = 51715,
TP2M_H = 4609,
B31 = 5632,
B1 = 4096,
M2_H = 4608,
B21_PRO = 785,
P1 = 1024,
T2S = 53250,
B50W = 51714,
T7 = 51717,
B50 = 51713,
Z401 = 2051,
B32R = 2050,
A63 = 2054,
T8S = 2053,
B32 = 2049,
B18S = 3585,
B18 = 3584,
MP3K_W = 4867,
MP3K = 4866,
K3_W = 4865,
K3 = 4864,
B3S_P = 272,
S6 = 261,
B3S = 256,
B3S_V2 = 260,
B3S_V3 = 262,
B3 = 52993,
A203 = 2818,
A20 = 2817,
B203 = 2816,
S1 = 51458,
JC_M90 = 51461,
S3 = 51460,
B11 = 51457,
B21_H = 784,
B21S_C2B = 776,
B21S = 777,
B21_L2B = 769,
B21_C2B = 771,
B21_C2B_V2 = 775,
B21 = 768,
B16 = 1792,
BETTY = 2561,
D101 = 2560,
D110_M = 2320,
HI_D110 = 2305,
D110 = 2304,
D11_H = 528,
D11S = 514,
FUST = 513,
D11 = 512,
ET10 = 5376,
P18 = 1026,
P1S = 1025,
T8 = 51718
}