AndBondStyle / niimprint

Python library for Niimbot label printers. Supports D11/B21/B1 via bluetooth or USB.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Printing early, then throwing out an extra label

danvelopment1 opened this issue · comments

Actually kind of glad I could log an issue, I can't find anywhere to have discussion or post my findings. I don't really (know how to) use git.

Anyway I have a K3w running over USB to an Ubuntu 23.04 laptop, which works great, I added listings in main to k3, set it as default and gave it a max_width of 640 and it happily printed labels correctly on 60mm*40mm white labels. Wanted to mention that but I couldn't find any place for discussion as such to post it without logging an issue, which I wasn't having at that point.

The K3w is equivalent to the B3s but it has a USB printer cable, WiFi capability and can suck in long labels from the back (eg like boarding passes etc).

Wrote a PHP application that builds an image from my inventory system, saves it to an accessible location and prints out the label, very happy.

However, when I switched down to 40mmx20mm labels, suddenly it prints early and then chonks out two labels (second one blank). Same result when direct from the CLI (so not the application).

Tried it with 320x160 labels, 304x144 labels, 250x100 labels and the B21_30x15mm_240x120px.png example all with the same results.

Tried changing the density as I saw in another issue (I've read them all) that there was an issue with it not completing prints, and different densities made a difference, but no change.

Command is
python3 niimprint -i /var/www/html/images/labels/standardLargeLabelSFF8643SGLANGLE1M.png -d 5

Ran it verbose for this output:

DEBUG | PngImagePlugin:call:204 - STREAM b'IHDR' 16 13
DEBUG | PngImagePlugin:call:204 - STREAM b'PLTE' 41 165
DEBUG | PngImagePlugin:call:204 - STREAM b'pHYs' 218 9
DEBUG | PngImagePlugin:call:204 - STREAM b'IDAT' 239 2667
DEBUG | printer:_log_buffer:146 - send: 55:55:21:01:05:25:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:31:01:01:31:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:23:01:01:23:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:33:01:01:33:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:01:01:01:01:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:02:01:01:02:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:03:01:01:03:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:04:01:01:04:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:13:04:00:90:01:30:b6:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:14:02:01:00:17:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:e3:01:01:e3:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:d3:03:00:8f:01:5e:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:e4:01:01:e4:aa:aa
DEBUG | printer:_log_buffer:146 - send: 55:55:f3:01:01:f3:aa:aa
DEBUG | printer:_log_buffer:146 - recv: 55:55:f4:01:01:f4:aa:aa

I've sent a print job for these labels from Niimbot desktop to success (printed one label in the right place, to rule out the printer).

And attached images (you can see it sort of starts printing immediately which results in data sitting on the gap between and sometimes on what would have been the sticker prior).

IMG_20240706_203357301
IMG_20240706_203851578_HDR
IMG_20240706_203858180_HDR
IMG_20240706_204159295_HDR
IMG_20240706_205340857_HDR

You can see in the last one (the 30x15) that it actually started printing on the label before it.

Gave bluetooth a try and it sucks the label back one, then lines it up and...does nothing.

There's a difference between the two labels, as pictured
IMG_20240706_211216831
And when you tear the smaller labels, they tear off at the bottom of the last label, with a big margin.
And when you tear the bigger labels, they tear off at the top of the next label, with no margin.
When I sliced off the margin with scissors to the top of the next, it printed correctly.
IMG_20240706_211457993

So it's something to do with how it recognises these particular smaller labels, where the Niim software must calculate or track where the label begins and waits to hit that point before starting printing. Whereas this is just starting printing (which works great for the big white ones, but not great for these small transparent ones).

However nothing changes the "it prints out a second blank label" thing, but it might also be a part of the same recognition issue, so I can just add a big margin at the top of the images to fix when it starts printing, but it will still skip every second label.

@danvelopment1 yeah, looks like an alignment issue. However, our code completely relies on the printer to do proper alignment automatically. I think I need to see some wireshark captures from an official app to figure it out. Maybe we're forgetting to send some extra "do alignment" command.

P.S. And regarding that the second blank label comes out, maybe it's related to alignment, but in the meantime you can try reducing the image height just a little bit, maybe it helps

@AndBondStyle If you can point me in the right direction, happy to run whatever you need. I don't need this fixed, I can just standardise on the bigger white ones which, by the way, is a MASSIVE benefit, so thanks heaps for your work. So happy to stick around and supply data.

I can just use these smaller ones for something else where I can't automate the data, and use the desktop/phone app for those.

For the image height thing, tried images down to 100px and same result, so definitely some sort of recognition thing on this label type.

@danvelopment1 I used a windows machine with wireshark to capture USB traffic (haven't tried bluetooth). You could also use some tips mentioned in #17 from @aprosvetova.

Cool, this is on a Linux machine and of course he suggests for Android and OSX. There will be a thousand ways to do it, but right now I don't know any of them yet.

I'll do a bit of research and see what I can kick out.

@danvelopment1 as far as I know, there's no way to run an official app on linux. And for android I believe you must use a rooted phone. So maybe the easiest way to test it on linux it to just use a windows VM or maybe an android emulator (however, I'm not sure if it would be easy to get USB/BT passthrough to work).

Oh I see you mean Official App as in "Official Niimbot App".

My primary computer is a Windows desktop, and this label printer is permanently affixed to this laptop but I liked the labels so much I have ordered another one. Once that arrives I'll hook it up to my desktop and give it a go.

I was thinking about the differences between the two labels and I theorise that the black lines are for transparent labels so that the machine can sense the location. Opened it up and there is CLEARLY two light sensors for this purpose.

As these little labels are transparent and the light will just pass through. Possibly this is sensing the black as the label (light can't pass through) and the white as the gap. As on the white labels, light can pass through on the gaps, and can't pass through on the label, it's inverted process. And you can see that when looking at the back of the labels from that earlier picture.

IMG_20240706_211216831

EG, start printing straight away, wait for light to be blocked, and that's the label itself (first black line), and when it stops being blocked that's the end of the label (woah, weird 2mm label, ah well), feed until the light is blocked again (next black line).

So I think this is a problem with transparent labels only, and not "small" labels on this machine.

The Niimbot software knows the label size and type, so it'll change its detection process accordingly.

IMG_20240707_092250994

@danvelopment1 also my code doesn't send some startup commands before starting the print (here) maybe it's as simple as that. You can try to uncomment these methods, disable result parsing (probably still broken) and see what happens. But anyway, it's better to look at some traffic captures

Have my new printer and now just playing printer.py.

A couple findings

set_label_type = 2, stops a second label from popping out, I'm guessing this = transparent
allow_print_clear doesn't seem to do anything (I thought maybe clear = transparent)
set_quantity surprsingly doesn't do anything, I changed it to 2, and it still only printed one

If I can't solve the problem on this new printer, I'll plug it into my desktop and install and play with WireShark and post results.

@danvelopment1 based on what we've found, k1w uses protocol version 4 (same as B1 uses) an it is not implemented in this project. You can see protocol differences here, for example.

What about label types, my findings are:

WithGaps = 1
Black = 2
Continuous = 3
Perforated = 4
Transparent = 5
PvcTag = 6
BlackMarkGap = 10
HeatShrinkTube = 11

@MultiMote Nice, that's great information, I'll give it a try and report back. The file had 1 >= n <= 3 so I didn't try past 3, and 3 flashed the light on the printer but didn't do anything, so maybe it was just confused by the continuous type.

So 1, with gaps must be normal, 2, black must mean the black gaps that I photographed earlier (which is why it only kicks out a single label when on 2), so maybe transparent handles how long that gap is and delays the print slightly. And if not, I'll try 10.

Guess we'll find out.

Also interested in the fact there are other types, like HeatShrinkTube, although I don't understand how that would work.

One thing I noticed, was that image printouts (eg logos) using this are better than via the official application.

The official app forces colour logos to go monochrome only, not greyscale. Whereas I get some nice greyscale detail using this on my logo, that the output is preferred.

@MultiMote @AndBondStyle Label Type 5 is perfect!

Updated the assertation for set_label_type to assert 1 <= n <= 11, self.set_label_type to 5 and the prints are 100% fixed.

So it's 100% the label types determining the behaviour.

Now I have to learn some python so I can work out how to add the ability to set the label type on demand (I'm a PHP developer and just been muddling around on this, the CLI invocation is coming from a PHP application).

Cool, got it, I copied the density references in main.py and printer.py and it worked. Was just guessing but it was easier than I expected.

So can set the labeltype from the CLI as needed.

main.py
@click.option( "-l", "--labeltype", type=click.IntRange(1, 11), default=1, show_default=True, help="Label Type, 1 = White, 5 = Transparent", )

def print_cmd(model, conn, addr, density, rotate, image, verbose, labeltype):

printer.print_image(image, density=density, labeltype=labeltype)

printer.py
def print_image(self, image: Image, density: int = 3, labeltype: int = 1):
self.set_label_type(labeltype)

@danvelopment1 so label type setting affects label alignment method done by the printer? That's good to know. Are you using original labels btw? I'm wondering if the printer can read label's RFID and decide what type it is, or it's done on the app side.

@danvelopment1 so label type setting affects label alignment method done by the printer? That's good to know. Are you using original labels btw? I'm wondering if the printer can read label's RFID and decide what type it is, or it's done on the app side.

Yep genuine labels, I have 7 different label types (6 normal white/coloured, and one small transparent) and the official app pops up with which one is loaded whenever I swap it.

And yep, label type determines how the printer acts, you can see it suck the label back one before printing every time to ensure it gets alignment correct.

As for whether the printer can set label type, VERY good question. I commented out set_label_type and printed a transparent label and it was correct, then I changed to big blue labels (white type) and it was correct! Then I changed it back to transparent to confirm the change recognition...and it was correct! So it's better to comment out set_label_type unless you want to override (no RFID labels).

Finally I sent an oversized print, and it didn't shrink (but it also didn't print too many to make up the whole picture). So you still need to know what size canvas you're working with (but the app could do resizing if it detected the label).

One thing that doesn't work and I can't make it do so (yet), is set_quantity. My function just loops one print x quantity field, which is slow but perfectly usable, I thought maybe self.set_quantity() would push a quantity like the app does so it just fires them out in short succession, but it still only prints one.

Tried moving the order of the function around but still the same result (when it's before label_density it doesn't print, so it does recognise SOMETHING).

@danvelopment1 set_quantity is probably broken due to incorrect implementation of print status checking. And that's not quite easily done because the protocol differs between printer models. If you'll have time, please submit some captures to our collection in #31. And maybe capture printing multiple quantity of labels (from an official app).

@danvelopment1

As for whether the printer can set label type, VERY good question. I commented out set_label_type and printed a transparent label and it was correct, then I changed to big blue labels (white type) and it was correct! Then I changed it back to transparent to confirm the change recognition...and it was correct! So it's better to comment out set_label_type unless you want to override (no RFID labels).

Did some research with my B1. I have rfid tag with label type = 1.

  1. Rfid tag is on reader. Sent SetLabelType packet to the printer with label type 5. Sent GetLabelType, printer responds with 5. Rebooted the printer. Sent GetLabelType, printers responds with 1.
  2. Rfid tag is on reader. Sent SetLabelType to the printer with label type 5. Opened and closed a lid (to read rfid tag again). Sent GetLabelType, printer responds with 1 again.
  3. Removed rfid tag. Sent SetLabelType to the printer with label type 5. Rebooted the printer. Sent GetLabelType, printer still responds with 5.

So:

  • The label type is persisted between printer reboots.
  • The label type will be overwritten when the RFID tag is read.