javl / InstaxBLE

MIT License
54 stars 6 forks source link

Issues with the WIDE Link #9

Closed Yasston closed 1 year ago

Yasston commented 1 year ago

Hello, thank you for this project which gave me hope to recycle an Instax WIDE Link to use in a raspberrypi-based photobooth. I have issues making it print photos though with the WIDE Link model.

First fix I had to do was correct the image size in InstaxBLE.py file, because the WIDE is 1260x840 : image

The rest seems to works, except for the Photos left that indicates 0/10, but goes ahead with the printing (The app shows 9/10, printing using the iOs app works I tested). It then seems the code gets stuck in a while loop when calling Event PRINT_IMAGE_DOWNLOAD_DATA:

[INFO] SimpleBLE: D:\a\SimpleBLE\SimpleBLE\simpleble\src\backends\windows\Utils.cpp:33 in initialize_winrt: CoGetApartmentType: cotype=-1, qualifier=0, result=800401F0
[INFO] SimpleBLE: D:\a\SimpleBLE\SimpleBLE\simpleble\src\backends\windows\Utils.cpp:41 in initialize_winrt: RoInitialize: result=0
Searching for instax printer...
Connecting to INSTAX-200021XX(IOS) [fa:ab:bc:50:2c:XX]
Connected
Attaching notification_handler
sending eventtype: EventType.SUPPORT_FUNCTION_INFO
> number of parts to send: 1
Notification handler:
        61 42 00 13 00 02 00 00 04 ec 03 48 02 7b 00 05 28 00 62
        Response event: EventType.SUPPORT_FUNCTION_INFO
event: EventType.SUPPORT_FUNCTION_INFO
04 ec 03 48
image size: 1260x840
sending eventtype: EventType.SUPPORT_FUNCTION_INFO
> number of parts to send: 1
Notification handler:
        61 42 00 0d 00 02 00 01 03 5f 00 10 da
        Response event: EventType.SUPPORT_FUNCTION_INFO
event: EventType.SUPPORT_FUNCTION_INFO
sending eventtype: EventType.SUPPORT_FUNCTION_INFO
> number of parts to send: 1

Printer details:
Model:               Instax Wide Link
Photos left:         0/10
Battery level:       95%
Charging:            False
Required image size: 1260x840px
MTU:                 244

Notification handler:
        61 42 00 11 00 02 00 02 39 00 00 0c 00 00 00 00 02
        Response event: EventType.SUPPORT_FUNCTION_INFO
event: EventType.SUPPORT_FUNCTION_INFO
sending eventtype: EventType.LED_PATTERN_SETTINGS
> number of parts to send: 1
Notification handler:
        61 42 00 08 30 01 00 23
        Response event: EventType.LED_PATTERN_SETTINGS
event: EventType.LED_PATTERN_SETTINGS
sending eventtype: EventType.LED_PATTERN_SETTINGS
> number of parts to send: 2
Notification handler:
        61 42 00 08 30 01 00 23
        Response event: EventType.LED_PATTERN_SETTINGS
event: EventType.LED_PATTERN_SETTINGS
sending eventtype: EventType.LED_PATTERN_SETTINGS
> number of parts to send: 1
printing image "example-wide.jpg"
Saved img with quality of 100
len of imagedata: 80911
Notification handler:
        61 42 00 08 30 01 00 23
        Response event: EventType.LED_PATTERN_SETTINGS
event: EventType.LED_PATTERN_SETTINGS
sending eventtype: EventType.PRINT_IMAGE_DOWNLOAD_START
> number of parts to send: 1
Notification handler:
        61 42 00 0c 10 00 00 00 00 03 84 b9
        Response event: EventType.PRINT_IMAGE_DOWNLOAD_START
event: EventType.PRINT_IMAGE_DOWNLOAD_START
sending eventtype: EventType.PRINT_IMAGE_DOWNLOAD_DATA
> number of parts to send: 10

I'm trying to print the 'example-wide.jpg' image that you provide, that I simply resized to 1260x840. I'm currently testing on Windows PC, but a previous try seemed to work on a Rapi 3B with the latest bullseye official raspi image. It appears the communication is made on the (IOS) bluetooth endpoint (and not the Android one as I saw you mention you had difficulties making a Raspi see the IOS BT connection endpoint). I do not own a Mac to capture BT traffic to help reverse engineer for the WIDE Link model, but if you think it can be done using an Android phone, I could do it with a bit of guidance.

Let me know if I could do anything else to help, I'd be ok to give you access remotely to a testing setup. Thank you !

javl commented 1 year ago

Hey Yasston, First a quick question: are you sure it's 1240x840? According to Fujifilm it should be 1260 x 800. See specs here: https://instax.com/link_wide/en/spec/ (means my value in the file was still wrong though, so thanks for pointing that out)

What might be happening, is that the 'chunk' size is incorrect. The image is chopped up into several parts which are sent to the printer one by one. You can see the sizes in Types.h, but the one for the wide is set to be the same as the square Basically the printer will confirm receiving data after every chunk, but if the size is not what is expected, this won't happen. We had this problem before when we used the square chunk size on the mini printer. Problem is, I'm not sure how to figure out what the right chunk size would be without a log.

Capturing the logs really is easiest on a Mac (also because Android uses a different protocol as you've seen). Maybe you know someone who has a Mac you could use for this?

javl commented 1 year ago

@Yasston You can uncomment this line to have the script print the expected image size: https://github.com/javl/InstaxBLE/blob/ab2c69f72b80bb23ed8a6e09f058b84c8a8fa94d/InstaxBLE.py#L104C1-L104C51

Yasston commented 1 year ago

Hey @javl thank you so much for your quick answer ! Yes I am pointing out that it should be 1260, not 1240 :) If you look closely at my screen capture you'll see I fixed it using (1260, 840) :) Yes I imagine it is indeed because it may require a different chunksize, or maybe even doesn't accept that we also send 812 packets for each chunk ^^ So unfortunately I don't know anyone with a Mac around :s I'll try to collect BT traces using Android though. If you have any pointers please send them, otherwise I'll have a look around and keep you posted. Many thanks !

Yasston commented 1 year ago

Also, indeed to confirm it is 1260x840, here is a capture of the raspebrry pi output the first time I ran the code without touching it : image

javl commented 1 year ago

@Yasston The instax specs say 1260 x 800, not 840, which is odd. But I guess your printer knows best what it wants so we'll go with the size it reports ;)

Yasston commented 1 year ago

Yes @javl, Height reported by the printer seems to be 840 :) as per previous screen capture. I'd also like to add that the other repo instax-link-web is using 840 for Height (Width was wrong though). But it also doesn't work with WIDE model, as I reported in this ticket here. Thank you so much again !!

javl commented 1 year ago

I don't have a lot of time at the moment, but let me quickly try something.

javl commented 1 year ago

@Yasston Ok, this is a weirdly small number, but could you try setting the chunksize (in Types.h) to 100?

Yasston commented 1 year ago

Thank you again for your time. So I started with a fresh clone of your repo. Changed the following : image and then on Types : image Then I simply resized the example-wide.jpg to 1260x840 and ran with -v option. No joy, here is the output : image

One thing I forgot to mention : about a minute after Disconnection, the light on the WIDE flashes yellow... Happened before, with this Python script and also with the instax-link-web app. Seems to indicate that there was an unsuccesful attempted print ? Not very helpful I imagine, but just in case... Also just to mention that in previous attemps I played with instax.send_led_pattern commands, they work fine, and they are pretty cool ^^ Thanks !

javl commented 1 year ago

Yeah the yellow flashing means it timed out waiting for a valid signal. I've tried finding the right value but no luck yet. I sort of know where to find it, but it's hiding from me. I'd suggest to just try some values, but seeing as the square already uses a weird value (1808) randomly selecting the right one might be impossible.

Yasston commented 1 year ago

I understand, I'll trying capturing the BT traffic from the Android app and let you know once I succeed. Thank you again for your time and help !

Yasston commented 1 year ago

Ok so I captured BT traffic between Android app and the printer, and isolated the packets sending the following events : PRINT_IMAGE_DOWNLOAD_START, PRINT_IMAGE_DOWNLOAD_DATA, and PRINT_IMAGE_DOWNLOAD_END

After the first PRINT_IMAGE_DOWNLOAD_START event, we can see there are exactly 100 packets for the event PRINT_IMAGE_DOWNLOAD_DATA, followed by a single packet for PRINT_IMAGE_DOWNLOAD_END event.

For the PRINT_IMAGE_DOWNLOAD_DATA event, we can see we have packets that are 926 bytes in length, with a payload that seems to be 912 bytes, minus the checksum byte at the end of the packet = 911 bytes (seems to be correct seeing the x03x8f after the Ab header, that is supposed to represent packet size info sent to the printer).

From my understanding, we then need to remove 6 bytes (Ab header + packet length + event code). That’s 905 bytes, times 100 which gives 90500 bytes for the total payload of the JPEG expected by the printer, is this correct ? How do you calculate the chunk size from that ? :) If you need me to attach the full capture log, please let me know. Thank you !

EDIT : turns out you also need to remove the packet index (4 bytes), and another byte at the end of the payload represneting the checksum. That gives 900 bytes, the chunksize ^^

javl commented 1 year ago

@Yasston

You know what, have you tried a chunksize of 900? Because I think the mini packets are also 911 bytes

I mentioned trying a size of 100 before because I found some mention of that number in the Android app, but I guess it wasn't the package size but the package amount like you just discovered. If 900 doesn't work could you upload or email your log? I've made a parser in the past that can recover the image from the log, allowing me to figure out the exact packet format.

Thanks for getting the logs, would be great to also have InstaxBLE support the Wide printer properly :)

Yasston commented 1 year ago

OMG ! it works !! It was there all along haha :) So the WIDE has the same chunksize setting than the mini (i.e. 900) 🤣 I just printed a real photo jpeg that was 1260x840. All good. Thank you again for your help ! Do you think there is a way to make it a bit faster ? I notice the majority of time is lost in sending the multiple packets chunks (this step in red) : image

Next step : make the script callable from the photobooth code, and put everything on the raspberry pi. Maybe I'll also have a look at the photos left attribute, it still mentions 0/10 although I can print without issues (the real value is actually now around 7/10)

javl commented 1 year ago

That's great! So weird though, that only the square seems to use a different chunksize. I'll update the source right now so you should be able to use the code without manual changes.

There are still two main issues:

  1. The printer acknowledges receiving packets, after which we can send the next one, but that means we need to somehow keep our Python script alive while waiting for the response (as normally the Python interpreter will exit when done). For this purpose we have this ugly hack of putting the script to sleep for 60 seconds (during the sleep we can still respond).
  2. The sending speed is very low on some devices. This seems to have something to do with the MTU size, basically a packet size decided between computer and printer. On the RPi we can speed up the printing by using a bluetooth socket instead, but this won't work on other platforms and I'd like this to be cross platform. edit: I notice your screenshots shows an mtu of 244 which I think should be fine. Is the printing really a lot slower than when you print from the app?

I'll close this issue, but feel free to open any new ones as needed, like maybe for the 'photos left' issue. I think I noticed this myself as well.

Yasston commented 1 year ago

Well honestly the speed is not that bad, it's maybe 5-7 seconds longer than from the Android app... It's just that for a photo booth usage, it could be a bit annoying ^^ Also it seems we could improve it a bit seeing that the Android app sends 100 packets, and I believe we send 182 packets if I'm not mistaken ? Anyway, you're right the sleep(60) is not ideal, especially for a photobooth usage (again), but my Python coding skills may not be good enough to help solve this problem. I'll have a look though, along with the Photos left issue :) Thank you again for all your help and time !!

javl commented 1 year ago

One thing you could do to help with the slow response in a photo booth setting is to play with visuals a bit.

In one installation I made a few year ago the display would show some sort of lottery interface where it would cycle through a list of options until it slowly stopped to select one, you know, like in a game show. In truth I picked the item as soon as the user pressed the button and the interface was just hiding a bunch of processing that had to be done in the background (like scraping some webpages related to the option). Maybe you can do something similar, like taking the photo and sending it off immediately, but then slowly revealing the photo on screen, as if it is developing. That way users have something visual to wait for, instead of some hidden printer that doesn't seem to do anything.

stephen5ng commented 7 months ago

I am trying the WIDE and immediately hit libc++abi: terminating due to uncaught exception of type pybind11::error_already_set: SystemExit: Unknown image size from printer: 1260x840

so it looks like the size change isn't in the repo yet?

Even after fixing that manually, I am having other issues with the WIDE--the sample image prints, but other images don't seem to print (and don't get a print confirmation message) after the packets have been sent. I've tried shrinking the image size in the python code as well as shrinking the source image itself, but it didn't seem to help.

I could switch to the SQUARE instead if that's better supported?