javl / InstaxBLE

MIT License
54 stars 6 forks source link

infinite loop at send_packet() #7

Closed KeitaroTakahashi closed 1 year ago

KeitaroTakahashi commented 1 year ago

Thank you so much for your great work, and I am thrilled to use your InstaxBLE!

I am just wondering that the latest code causes infinite loop at send_packet() at the place shown below. while self.waitingForResponse and not self.dummyPrinter and not self.cancelled: self.log("sleep") sleep(0.05)

I am using both Instax Link 1 and 2 and without the while loop, it works fine, but sometimes it crashes with "segmentation fault". I thought that's the reason you added the while loop but, could you please let me know if there is anything I should do to get out from the loop?

Thanks a lot.

javl commented 1 year ago

Do you know after what event this happens? Like after sending a LED signal, or during printing?

Normally you get a response from the printer after every message you send. If there is no response (and you get into a loop) it means something went wrong. I could add some soort of timeout, like if there is no response within 2 seconds it will break the loop but this could mean you end up in some weird situation with the printer.

KeitaroTakahashi commented 1 year ago

Thanks for your reply. The loop enters after PRINT_IMAGE_DOWNLOAD_START is called.

When I comment out the while loop, then it successfully outputs a printed photo.

Here is a log I got.

python InstaxBLE.py
Searching for instax printer...
Connecting to INSTAX-10618286(IOS) [96711AEC-B4B3-605C-C30A-81AFDA0F7376]
Connected
sleep
2023-05-27 17:37:39.336 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
sleep
2023-05-27 17:37:39.391 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
sleep
2023-05-27 17:37:39.447 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO

Printer details: 
Model:               Instax Mini Link
Photos left:         10/10
Battery level:       80%
Charging:            False
Required image size: 600x800px
MTU:                 182

sleep
2023-05-27 17:37:39.502 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.LED_PATTERN_SETTINGS
sleep
2023-05-27 17:37:39.556 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.LED_PATTERN_SETTINGS
has own image path
printing image "XXXXXXXXXX.jpg"
Saved img with quality of 94
sending first of image
sleep
2023-05-27 17:37:39.663 Python[7133:183778] Peripheral ready to send: <CBPeripheral: 0x60000064c1a0, identifier = 96711AEC-B4B3-605C-C30A-81AFDA0F7376, name = INSTAX-10618286(IOS), mtu = 185, state = connected>
event: EventType.PRINT_IMAGE_DOWNLOAD_START
Img packets left to send: 115
send next packet
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
maemaemae3 commented 1 year ago

Hi, I have same issue, but I also cannot print anything even if removing the while loop. I checked it in Mac mini (M2 Pro), with macOS Ventura and Windows. instax mini firmware version is latest (0104)

It blinks yellow for waiting a while, so it looks like its occuring error. Could you give me a hand about how to debug?

$ python InstaxBLE.py -v
Searching for instax printer...
Connecting to INSTAX-XXXXXXX(IOS) [C9444AFF-4624-E0DB-F4CF-985390767BF1]
Connected
sleep
2023-05-27 19:14:26.557 python[20629:130643] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
sleep
2023-05-27 19:14:26.612 python[20629:130643] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
sleep
2023-05-27 19:14:26.662 python[20629:130644] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO

Printer details:
Model:               Instax Mini Link
Photos left:         5/10
Battery level:       80%
Charging:            False
Required image size: 600x800px
MTU:                 182

sleep
2023-05-27 19:14:26.718 python[20629:130644] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
sleep
event: EventType.LED_PATTERN_SETTINGS
sleep
2023-05-27 19:14:26.821 python[20629:130644] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.LED_PATTERN_SETTINGS
use example image
printing image "example-mini.jpg"
Saved img with quality of 100
Printing is disabled, sending all packets except the actual print command
sending first of image
sleep
2023-05-27 19:14:26.925 python[20629:130644] Peripheral ready to send: <CBPeripheral: 0x6000006301a0, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.PRINT_IMAGE_DOWNLOAD_START
Img packets left to send: 51
send next packet
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep
sleep

Website didn't work either with error below.

PRINTIN
index-1c6b3261.js:16 > 41 62 00 0f 10 00 02 00 00 00 00 00 8a 4b 66
index-1c6b3261.js:16 Packet 0/11 true
index-1c6b3261.js:16 Error: Notification timeout
  at index-1c6b3261.js:11:24494

However I can print images from official app so I'm thinking instax mini itself is working well.

javl commented 1 year ago

Can you try removing the loop but add a small delay like 'sleep(0.1)'

maemaemae3 commented 1 year ago

@javl thank you for your support! looks like print process ends without printing anything with no error.

$ python InstaxBLE.py -v
Searching for instax printer...
Connecting to INSTAX-XXXXXXX(IOS) [C9444AFF-4624-E0DB-F4CF-985390767BF1]
Connected
2023-05-27 19:53:24.996 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
2023-05-27 19:53:25.097 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO
2023-05-27 19:53:25.202 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.SUPPORT_FUNCTION_INFO

Printer details:
Model:               Instax Mini Link
Photos left:         5/10
Battery level:       80%
Charging:            False
Required image size: 600x800px
MTU:                 182

2023-05-27 19:53:25.304 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.LED_PATTERN_SETTINGS
2023-05-27 19:53:25.409 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.LED_PATTERN_SETTINGS
use example image
printing image "example-mini.jpg"
Saved img with quality of 100
Printing is disabled, sending all packets except the actual print command
sending first of image
2023-05-27 19:53:25.567 python[25377:164882] Peripheral ready to send: <CBPeripheral: 0x60000235c000, identifier = C9444AFF-4624-E0DB-F4CF-985390767BF1, name = INSTAX-XXXXXXX(IOS), mtu = 185, state = connected>
event: EventType.PRINT_IMAGE_DOWNLOAD_START
Img packets left to send: 51
send next packet
sending cancel command
KeitaroTakahashi commented 1 year ago

@javl @maemaemae3

I guess it is because PRINT_IMAGE packet is missing to send at elif event == EventType.PRINT_IMAGE_DOWNLOAD_END: pass

For my case, I added following codes and then it worked OK (... and you removed while loop discussed above)

elif event == EventType.PRINT_IMAGE_DOWNLOAD_END: if len(self.packetsForPrinting) > 0 and not self.cancelled: packet = self.packetsForPrinting.pop(0) self.send_packet(packet)

javl commented 1 year ago

@KeitaroTakahashi Thanks, I'll check it out when I get home

maemaemae3 commented 1 year ago

@KeitaroTakahashi it looks like adding those lines didnt help... It looks like packet is queued correctly in self.packetsForPrinting but not sent to instax (because log only outputs event: EventType.PRINT_IMAGE_DOWNLOAD_START)

let me investigate a little more

javl commented 1 year ago

Did you enable printing? By default it doesn't send that last packet (check the note in the example)

maemaemae3 commented 1 year ago

yep, I remove comment of this line https://github.com/javl/InstaxBLE/blob/d6af009e5e247747a243e32722af0a65d7402f04/InstaxBLE.py#L503

javl commented 1 year ago

I'm not completely sure how to fix this (yet).

The idea behind the code is this: Your image is send piece by piece. After sending a piece a waitingForResponse variable is set to True, and a loop starts which keeps executing a very short sleep(). This is done so the script doesn't stop like a Python script normally does when all code has been executed.. When the printer has received a message, it will send back a response. At that time we check what the response is (it tells you what it responded to) and we set waitingForResponse back to False. This stops the endless loop and lets the code continue to the next packet, repeating this until everything has been send.

What seems to happen is that this waitingForResponse variable doesn't get set to False properly, or the while loop doesn't see the changed value. The notifier script called by messages received from the printer triggers for the PRINT_IMAGE_DOWNLOAD_START packet (which you saw in your log) but doesn't get triggered for the next PRINT_IMAGE_DOWNLOAD_DATA packet for some reason. Could be a multi threading issue, or just something dumb on my part.

I'm trying to find a way to get this to work reliably but need to find some time to do so and test.

javl commented 1 year ago

I did some testing tonight and might have found the issue! I'll try a fix tomorrow. Fingers crossed 🤞🏼

KeitaroTakahashi commented 1 year ago

Great! can't wait for seeing it!!

javl commented 1 year ago

Ok, so that doesn't seem to have been it...

Looking at the logs I see the printer responds to both IMAGE_PRINT_DOWNLOAD_START and IMAGE_PRINT_DOWNLOAD_DATA but for some reason my notifier doesn't trigger for the _DATA one, leading to us waiting indefinitely...

image

javl commented 1 year ago

I think I found the problem!

The script used to do this:

enter `send_packet` => send our data => wait for a response => exit `send_packet` (continuing the code)

it seems this was causing trouble and was blocking notification_handler from getting called properly. I've moved the wait loop up, so it now works like this:

enter `send_packet' => check if previous message had a response, otherwise wait => if there was a response, send new data => exit `send_packet`

This does mess up some other timing elements so for now I had to add a long delay before the end of the script (sleep(60)) to prevent the script from exiting before we're done. This can be done more neatly but should work for now.

I'm sure something will go wrong,but I was able to print by calling the script like python3 instaxBLE.py -i myimage.jpg -p -v (-p allows actual printing, -v shows you verbose information as it runs)

Please pull the latest update and give it another go, @KeitaroTakahashi & @maemaemae3!

maemaemae3 commented 1 year ago

PXL_20230529_125749948 Hooray. I was able to print! Thanks a lot!

javl commented 1 year ago

Great! Now that I know what caused the problem I 'just' need to find a proper way of fixing this. The problem with this whole setup is that Python scripts normally exit after the last line has been executed, but we need to wait for a response from the printer which can come after our own last commands. But we have to wait in a way that doesn't block the response from coming in. Maybe I need to add some sort of threading... Not sure, but happy to hear the code is somewhat usable again (and I don't think this 60 second delay will be much of a problem for most programs as you're probably not going to print non-stop anyway).

KeitaroTakahashi commented 1 year ago

Super!! Thank you so much for your help!