BetaRavener / uPyLoader

File transfer and communication tool for MicroPython boards
MIT License
355 stars 76 forks source link

File interactions over WiFi not working #80

Open TizioMaurizio opened 3 years ago

TizioMaurizio commented 3 years ago

Anytime i double click a file in the right part of the main panel or try to download one by clicking Transfer the program hangs with 0% in the File Transfer popup window. File list and terminal seem to work properly, trying to transfer a file from local to board doesn't seem to have any effect.

I'm connecting to an ESP32-CAM board over WiFi. I get the problem in both .exe version and main.py ran from Pycharm IDE imported project, in pycharm I can also read an exception sometime after the program freezes:

Exception in thread Thread-2: Traceback (most recent call last): File "C:\Users\Maurizio\anaconda3\envs\pythonProject\lib\threading.py", line 932, in _bootstrap_inner self.run() File "C:\Users\Maurizio\anaconda3\envs\pythonProject\lib\threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "C:\Users\Maurizio\Documents\Arduino\uPyLoader\src\connection\wifi_connection.py", line 187, in _read_file_job (sz,) = struct.unpack("<H", self.ws.read(2)) File "C:\Users\Maurizio\Documents\Arduino\uPyLoader\src\connection\websocket.py", line 63, in read hdr = self.recvexactly(2) File "C:\Users\Maurizio\Documents\Arduino\uPyLoader\src\connection\websocket.py", line 52, in recvexactly raise TimeoutError() TimeoutError

I would like to congratulate for your job anyway, I'm pretty new to Micropython on a microcontroller and after working with webrepl for sometime I was about to implement a GUI for file browsing myself, but after a quick search I found this project that seems really promising!

P.S. I also noticed that your program's terminal is way faster than Webrepl's one which is a big bonus

BetaRavener commented 3 years ago

Hi and thanks for detailed report. The TimeoutError points out the fact that we didn't receive response from the device. It should be handled properly so that the transfer breaks when it happens, but it's not the issue on itself.

It's actually the device failing to reply to a request for another chunk of data. It, however, seems to react to the initial message of the protocol, otherwise it would assert here. You could always double-check the values there using PyCharm's debugger.

It could also be an issue with the specific micropython implementation, but if webrepl can transfer files, this is unlikely.

I'm more worried that there might have been breaking change in the protocol (noted here "At this point, this protocol is in early research/design/proof-of-concept phase. The only available specification of it is the reference code implementation, and the protocol is subject to frequent and incompatible changes."). Indeed, it looks like a different value is passed in webrepl_cli than in my implementation. You could try changing that value from b"\1" to b"\0", but that change is over 4 years old, so I'm not sure it will help. The value of the byte actually doesn't seem to matter, it just unblocks the device so it sends more data.

Last thing you could try is being connected also to UART while doing wifi transfer. Sometimes errors and exceptions gets spilled there.

TizioMaurizio commented 3 years ago

Oh my god changing from b"\1" to b"\0" worked hahahaha, anyway just out of curiosity what is the "True" right after it for?

Here is what I could see through UART using Putty: (sorry for the messy post but the pasted text from putty and python consoles messes with the format characters)

>>> import os; os.stat("main.py") (32768, 0, 0, 0, 0, 0, 2387, 94, 94, 94) >>> assertion "filebuf[0] == 0" failed: file "../../extmod/modwebrepl.c", line 275, function: _webrepl_read abort() was called at PC 0x4016a0db on core 1

ELF file SHA256: 0000000000000000000000000000000000000000000000000000000000000000

Backtrace: 0x400920a7:0x3ffce350 0x400923c5:0x3ffce370 0x4016a0db:0x3ffce390 0x400f39ba:0x3ffce3c0 0x400f3a15:0x3ffce6f0 0x400f5b82:0x3ffce710 0x400f628e:0x3ffce790 0x400e373d:0x3ffce7b0 0x400df75d:0x3ffce7d0 0x400df845:0x3ffce7f0 0x400e049c:0x3ffce820 0x400f8d8d:0x3ffce8a0 0x400f5ed2:0x3ffce8d0 0x40104341:0x3ffce8f0 0x4010495f:0x3ffce910 0x400f5cf8:0x3ffce950 0x4009b022:0x3ffce980

Rebooting...

I also went back in the serial log and found some weird command entanglement in one for the previous crashes, but I can't recall if it's because of something extra I did other than just loading the file

>>> >>> import os; os.stat("main.py") Traceback (most recent call last): File "", line 1 SyntaxError: invalid syntax >>> (32768, 0, 0, 0, 0, 0, 2387, 94, 94, 94) (32768, 0, 0, 0, 0, 0, 2387, 94, 94, 94) >>> >>> assertion "filebuf[0] == 0" failed: file "../../extmod/modwebrepl.c", line 275, function: _webrepl_read Traceback (most recent call last): File "", line 1 SyntaxError: invalid syntax >>> abort() was called at PC 0x4016a0db on core 1 Traceback (most recent call last): File "", line 1 SyntaxError: invalid syntax

>>> ELF file SHA256: 0000000000000000000000000000000000000000000000000000000000000000 Traceback (most recent call last): File "", line 1 SyntaxError: invalid syntax >>> >>> Backtrace: 0x400920a7:0x3ffce350 0x400923c5:0x3ffce370 0x4016a0db:0x3ffce390 0x400f39ba:0x3ffce3c0 0x400f3a15:0x3ffce6f0 0x400f5b82:0x3ffce710 0x400f628e:0x3ffce790 0x400ed0x3ffce7d0 0x400df845:0x3ffce7f0 0x400e049c:0x3ffce820 0x400f8d8d:0x3ffce8a0 0x4002fce980 Traceback (most recent call last): File "", line 1 SyntaxError: invalid syntax >>> >>> Rebooting...

BetaRavener commented 3 years ago

Nice! The True value marks file transfer, the function is implemented here though most likely I pulled that file from somewhere and forgot to comment it.

Regarding the output, this part is sent by me to get file size for progress bar:

import os; os.stat("main.py")
(32768, 0, 0, 0, 0, 0, 2387, 94, 94, 94)

The rest is result of the websocket protocol I believe, but I have no idea what's happening there.

BetaRavener commented 3 years ago

I didn't see many reports of this issue so I'm not sure if changing the value for everyone is good idea, or it needs to be based on micropython version (or maybe other factors). I can't promise, but I'll try to look into this in near future and make adjustments.