MultiMote / niimbluelib

🖨 A library for the communication with NIIMBOT printers
https://multimote.github.io/niimbluelib/
MIT License
14 stars 4 forks source link

Tested models #1

Open MultiMote opened 2 months ago

MultiMote commented 2 months ago

There is a list of tested models. If you own other model or you have issues with model listed here, please write a comment. You can test your model with the niimblue project.

Tested by me, fully supported:

Tested by other people:

f870103 commented 2 months ago

D11 tested on:

Please let me know if you need any additional information or specific details about this model.

nyarau commented 1 month ago

D11 tested on Android. While it shows an error after clicking Print, it prints just fine. The hardware and firmware version must be very old since I bought it around 2020 and didn't use it for a long time. info print

Thank you so much for the work!

MultiMote commented 1 month ago

@nyarau That's very odd. It seems like the client is not even able to get the printer information. What is your printer's hardware and firmware version (you can see it in official NIIMBOT app)? Can you try it on PC (connect with USB cable if printer supports it or use BLE adapter if you have it) and send browser logs (usually press F12, console tab)? Alternatively you can copy logs on Android browser supports DevTools (Kiwi Browser for example).

nyarau commented 1 month ago

Firmware 3.60 Hardware 3.01 Judging by the number it's probably too old. It's printing just fine so I don't plan to update anything, bigger chance they get something locked down in a new version than giving me any meaningful improvement. Here's browser log logs

MultiMote commented 1 month ago

@nyarau it's useful information. Looks like response for PrinterInfo packet is not same as in other models. I'll try to figure out how to handle it. Can you also print some label and check logs again? I need to know how your model respond to PrintStatus packet.

nyarau commented 1 month ago

There you go logs-print.txt

MultiMote commented 1 month ago

Pushed some changes. Model detection should work at least (if other info packets are not have different format, let me know if there is some other errors in the browser logs after printer connection). Also added error codes (you receiving "Printer Busy" for some reason).

It would be very useful if you can record packet dump of successful print with the official app. Method may vary between ROMs, but generally it is:

nyarau commented 1 month ago

I tried the new version, still can't get device info:

new NiimbotBluetoothClient
index-m_AmWyhH.js:33 >> 03 55 55 c1 01 01 c1 aa aa (Connect)
index-m_AmWyhH.js:33 << 55 55 c2 01 01 c2 aa aa (In_Connect)
index-m_AmWyhH.js:33 >> 55 55 40 01 08 49 aa aa (PrinterInfo)
index-m_AmWyhH.js:33 << 55 55 48 01 02 4b aa aa (In_PrinterInfoPrinterCode)
index-m_AmWyhH.js:33 Unable to fetch printer info.
connect @ index-m_AmWyhH.js:33
await in connect
h @ index-m_AmWyhH.js:74
index-m_AmWyhH.js:33 Error: Array length must be 2
    at yl.u8ArrayLengthEquals (index-m_AmWyhH.js:33:12632)
    at Vi.bytesToI16 (index-m_AmWyhH.js:33:12076)
    at s.getPrinterModel (index-m_AmWyhH.js:33:24979)
    at async o.fetchPrinterInfo (index-m_AmWyhH.js:33:74568)
    at async o.connect (index-m_AmWyhH.js:33:68768)
    at async HTMLButtonElement.h (index-m_AmWyhH.js:74:3642)
connect @ index-m_AmWyhH.js:33
await in connect
h @ index-m_AmWyhH.js:74
index-m_AmWyhH.js:33 onConnect

Error message when printing is now: Error: Print error (In_PrintError packet received, code is 9 - PRINTER_BUSY)

Official Android app refused to run because my device is rooted, unfortunately. I may find a way to dump the packets in the future but don't count on me.

MultiMote commented 1 month ago

I tried the new version, still can't get device info:

Copy-paste mistake, sorry. Fixed.

Official Android app refused to run because my device is rooted, unfortunately.

If your device rooted with Magisk, you can add NIIMBOT to DenyList. My device is rooted too and I can run app without problems with Zygisk&DenyList.

I may find a way to dump the packets in the future but don't count on me.

No problem, I don't want to bother you.

nyarau commented 1 month ago
new NiimbotBluetoothClient
index-B2UsUqlZ.js:33 >> 03 55 55 c1 01 01 c1 aa aa (Connect)
index-B2UsUqlZ.js:33 << 55 55 c2 01 01 c2 aa aa (In_Connect)
index-B2UsUqlZ.js:33 >> 55 55 40 01 08 49 aa aa (PrinterInfo)
index-B2UsUqlZ.js:33 << 55 55 48 01 02 4b aa aa (In_PrinterInfoPrinterCode)
index-B2UsUqlZ.js:33 >> 55 55 40 01 0b 4a aa aa (PrinterInfo)
index-B2UsUqlZ.js:33 << 55 55 4b 05 c3 ******* aa aa (In_PrinterInfoSerialNumber)
index-B2UsUqlZ.js:33 >> 55 55 40 01 0d 4c aa aa (PrinterInfo)
index-B2UsUqlZ.js:33 Unable to fetch printer info.
connect @ index-B2UsUqlZ.js:33
index-B2UsUqlZ.js:33 Error: Timeout waiting response (waited for 4f, 47, 4d, 4a, 41, 4c, 43, 46, 48, 4b, 49, 42)
    at index-B2UsUqlZ.js:33:69554
connect @ index-B2UsUqlZ.js:33

index-B2UsUqlZ.js:33 onConnect

And print

...
>> 55 55 83 10 00 7b 00 00 05 02 00 2b 00 2c 00 2d 00 3e 00 3f c4 aa aa (PrintBitmapRowIndexed)
index-B2UsUqlZ.js:33 >> 55 55 84 03 00 7d 33 c9 aa aa (PrintEmptyRow)
index-B2UsUqlZ.js:33 >> 55 55 e3 01 01 e3 aa aa (PageEnd)
index-B2UsUqlZ.js:33 << 55 55 e4 01 01 e4 aa aa (In_PageEnd)
index-B2UsUqlZ.js:33 << 55 55 db 01 09 d3 aa aa (In_PrintError)
index-B2UsUqlZ.js:33 >> 55 55 a3 01 01 a3 aa aa (PrintStatus)
index-B2UsUqlZ.js:33 << 55 55 e0 02 00 01 e3 aa aa (In_PrinterPageIndex)
index-B2UsUqlZ.js:70 Error: Timeout waiting response (waited for b3, db)
    at index-B2UsUqlZ.js:33:69554
$ @ index-B2UsUqlZ.js:70
await in $
(anonymous) @ index-B2UsUqlZ.js:70
await in (anonymous)
hl @ index-B2UsUqlZ.js:33
(anonymous) @ index-B2UsUqlZ.js:33
vl @ index-B2UsUqlZ.js:33
Promise.then
uu @ index-B2UsUqlZ.js:33
pu @ index-B2UsUqlZ.js:33
(anonymous) @ index-B2UsUqlZ.js:33
P @ index-B2UsUqlZ.js:70
10index-B2UsUqlZ.js:33 >> 55 55 a3 01 01 a3 aa aa (PrintStatus)
index-B2UsUqlZ.js:33 >> 55 55 f3 01 01 f3 aa aa (PrintEnd)
index-B2UsUqlZ.js:33 << 55 55 f4 01 01 f4 aa aa (In_PrintEnd)
nyarau commented 1 month ago

I managed to dump the packets from iOS app with the this method: https://novelbits.io/debugging-sniffing-secure-ble-ios/ (no Apple developer account required, any iCloud account works) I added annotations myself according to your code. dump

MultiMote commented 1 month ago

Nice! Can you send a text version please?

nyarau commented 1 month ago

Long packets in txt export are truncated dump.txt

MultiMote commented 1 month ago

@nyarau, I figured it out and made some changes. Your dump helped me. In the old protocol version, there is no need to check print progress. Also I suppressed errors (your printer does not support MAC address getting, for example) in the initial negotiation. So printer info fetching should work.

Use print task version V1 for printing with your printer.

nyarau commented 1 month ago

Thank you so much for the work!

Printer info is now mostly working. The serial number is literal HEX code in the packet (C3456789, 8 characters) without any decoding. info

However printing no longer works properly, it prints the first page just fine, but any following prints get a timeout until a reconnect. V1 and V3 have the same behavior. Cancel print doesn't help. print

MultiMote commented 1 month ago

Oh, why it is so many protocol differences? 😥

Serial is sending as string in newer models.

image

What about printing - if you have some free time, can you please make text dump of two prints with official app (quantity is 1, but print twice)? Honestly, I don't understand what's wrong.

nyarau commented 1 month ago

Here you go, 1.txt and 2.txt are exactly as you requested, 3.txt contains more prints and one of them are 5 copies instead of 1. Every dump started before the app was open and ended after the app was killed. Somehow the printer doesn't reply RFID info today and app complains about non genuine labels, but NiimBlue can still get it like before. 1.txt 2.txt 3.txt

MultiMote commented 1 month ago

Seems like I get it.

In old protocol printer is sending 0xE0 (In_PrinterPageIndex) status packets by themselves during print. In newer protocols it's exchange of 0xa3 (PrintStatus) → (0xb3) In_PrintStatus. I think printer stops responding because we send PrintEnd before print is actually finished.

Added new status check algorithm for V1 print task. Hopefully, it will work. Serial number parsing fixed too.

nyarau commented 1 month ago

I figured it out! You must turn heartbeat on. Even if the printer is locked out like my previous report, as long as you send a heartbeat, it works again. I also tested with the initial NiimBlue version from 3 days ago, this behavior is consistent.

MultiMote commented 1 month ago

Oddly enough. What is the behavior of the latest version, but without heartbeat?

I don't recommend using heartbeat now, it is not turning off automatically in some cases and may break prints.

nyarau commented 1 month ago

Here's a log of two successful prints in quick succession log

nyarau commented 1 month ago

It's the same behavior across all versions, no heartbeat no second print, once heartbeat is on it works no problem at all. I'd rather have broken prints than can't print at all :smile:

MultiMote commented 1 month ago

Oh, okay. Then I'll work on heartbeat next. Apparently it's mandatory in older models.

MultiMote commented 1 month ago

Fine-tuned lib and frontend heartbeat code. It will now start automatically after connect and will be paused on prints. Hopefully this won't cause random disconnects for some people 😁

nyarau commented 1 month ago

Thanks a lot for your work! My printer is finally working as expected.

I did some fiddling myself, here is my finding: Periodic heartbeats aren't necessary, one heartbeat before a print is all it needs. I commented out all automatic heartbeats, then added this line to PrintPreview.svelte#L74, it worked perfectly.

await $printerClient.abstraction.heartbeat().catch(console.error)
tbslusser1 commented 1 month ago

I can confirm that this library works as-is with a few caveats for an M2 (2024) model NIIMBOT printer.

modelId: 4608 hardwareVersion: 2.57 softwareVersion: 2.73

  1. An integer dpmm must be selected (it's a 300 dpi printer so ≈11.81dpmm). Not selecting an integer dpmm will cause a timeout error when trying to print
  2. For some reason, a valid RFID tag must be near/inside the printer to 'spoof' a label (same timeout error occurs otherwise)
  3. I could not get the printer to show via bluetooth (Edge browser/Windows 11) but that is probably a result of me relying on Edge to do something correctly
  4. The D110 print task caught me off guard as it just kept repeating prints

Otherwise, flawless operation!

MultiMote commented 1 month ago

@tbslusser1

2. For some reason, a valid RFID tag must be near/inside the printer to 'spoof' a label (same timeout error occurs otherwise)

Older models (Like D110) ignored tag completely. Newer models (like B1) degraded print quality (density) when tag was not present. Looks like newest models not printing at all without tag 🤔

The printer usually reads the tag once after closing the lid, so you can put the tag, close the lid, and remove the tag (this was in previous models).

3. I could not get the printer to show via bluetooth (Edge browser/Windows 11) but that is probably a result of me relying on Edge to do something correctly

Bluetooth filter was too small. Fixed in https://github.com/MultiMote/niimbluelib/commit/6dde5813af81cd5a3368cb16f3bb4c7c04a837ea

4. The D110 print task caught me off guard as it just kept repeating prints

It's a fairly common behavior on new models when using older print task 😁 So what printing task have you chosen? And what hardware and software versions displayed in the official app? In this library these versions may be displayed wrong.

tbslusser1 commented 1 month ago

It's a fairly common behavior on new models when using older print task 😁 So what printing task have you chosen? And what hardware and software versions displayed in the official app? In this library these versions may be displayed wrong.

Using the B1 print task worked fine for me.

Within the official app, here's the reported hardware and software version:

Firmware version: 1.17 (with an update available) Hardware version: 1.01

zzaabaazz commented 2 weeks ago

Have D101, used profile D110 (anything else doesnt work) 1st try it just scrolls without printing anything 2nd try it prints really quick and doesnt stop unless i cancel Firmware version: 9.06 Hardware version: 9.10

MultiMote commented 2 weeks ago

@zzaabaazz Please post detailed printer info (gear icon near printer name) from niimblue. I hope we can get your printer to print normally.

zzaabaazz commented 2 weeks ago
Printer info:
connectResult: 3
protocolVersion: 0
modelId: 2560
serial: G302020043
mac: 00:02:43:74:0a:36
charge: 2
autoShutdownTime: 4
labelType: 1
hardwareVersion: 0x090a
softwareVersion: 0x0906
Model metadata:
model: D101
id: 2560
dpi: 203
printDirection: left
printheadPixels: 192
paperTypes: 1,5
densityMin: 1
densityMax: 3
densityDefault: 2
Heartbeat data:
paperState: -1
rfidReadState: -1
lidClosed: true
powerLevel: 2
zzaabaazz commented 2 weeks ago

Wait, the B1 profile just worked perfectly EDIT: i checked all profiles again: B1, B21_V1 and V5 work flawlessly D110 and D11_V1 behave simmilary to what i described before