forked from moonglow/FlashForge_Marlin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ff_flash_firmware.py
executable file
·154 lines (126 loc) · 4.18 KB
/
ff_flash_firmware.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
'''
Original script by: https://gist.github.com/zerog2k
Usage: ./ff_flash_firmware.py /path/to/firmware.bin
'''
import hashlib
import sys
from time import sleep
import usb
def to_string(byt):
return ''.join([chr(x) for x in byt])
"""
Send command to printer and wait for a reply until we either get 'ok' or timeout
Parameters:
command : string containing command M/G g-code command
expectreply : set True to generate exception if printer does not respond
Returns:
True if the printer responded
"""
def send_command(command, expectreply=True):
command = '~{}\r\n'.format(command)
print('>>>' + command.strip())
printer.write(CONTROL_ENDPOINT_ADDR, command)
# now get response
timeout = 1000 # wait up to 1 seconds for initial response
response = ''
while True:
try:
ret = printer.read(BULK_IN_ENDPOINT_ADDR, timeout).tobytes()
timeout = 500 # subsequent responses should be quicker
response = to_string(ret)
print('<<<' + response.strip().replace('\r', '').replace('\n', '\n<<<'))
if any(x in response.lower() for x in ['error','failed']):
raise Exception('printer returned error')
if 'ok\r\n' in response:
# printer finished responding
print()
return True
except usb.core.USBTimeoutError:
# no more response - we can get here after no response or getting a partial response
# and then timeout waiting for an 'ok'
if expectreply:
raise Exception('printer did not respond')
print()
return False
TARGET_FIRMWARE_NAME = 'firmware.bin'
FLASHFORGE_VENDOR_IDS = [0x2a89, # Dremel
0x2b71, # FlashForge
0x0315 # FlashForge bootloader
]
MAX_WAIT_TIME = 0.5 # 500 milliseconds
RETRY_COUNT = 20
CONTROL_ENDPOINT_ADDR = 0x01
BULK_OUT_ENDPOINT_ADDR = 0x03
BULK_IN_ENDPOINT_ADDR = 0x81 # by default, search for 'bEndpointAddress' in
# usb details if this is not the case
if len(sys.argv) != 2:
# (first argument is this script name)
print('Expecting firmware file - usage: ./ff_flash_firmware.py '
'/path/to/firmware.bin')
print()
exit()
firmware = sys.argv[1]
# calculate checksum of the firmware
m = hashlib.md5()
try:
fw = open(firmware, 'rb')
m.update(fw.read())
firmware_checksum = m.hexdigest()
firmware_size = fw.tell()
fw.seek(0)
except:
print('Error opening firmware file: ', firmware)
print()
exit()
print('Flashing firmware: ', firmware)
print('Searching for Flashforge printers ...')
printer = None
retry = 1
while not printer:
if retry >= RETRY_COUNT:
print('Did not find any Flashforge compatible printers, check your connections, '
'reboot the printer and try again.')
print()
exit()
for FLASHFORGE_VENDOR_ID in FLASHFORGE_VENDOR_IDS:
printer = usb.core.find(idVendor=FLASHFORGE_VENDOR_ID)
if printer:
print('Found printer:\n\n', printer)
print()
break
retry = retry + 1
sleep(MAX_WAIT_TIME)
try:
# setup the configurations before the communication
printer.set_configuration()
# start control
retry = 7
print('Initiating control loop...')
while True:
retry -= 1
# try up to 'retry' times to connect, on last attempt will error if no response
if send_command('M601 S0', retry == 0):
break
# start fw write
print('Writing firmware...')
send_command('M28 {} 0:/sys/{}'.format(firmware_size, TARGET_FIRMWARE_NAME))
# write fw to endpoint
printer.write(BULK_OUT_ENDPOINT_ADDR, fw.read(),
5000) # seems like i was getting timeouts below about 1500ms
# finish fw write
print('Finished writing, sending file end comand...')
send_command('M29 {}'.format(firmware_checksum))
# trigger fw flash on next boot?
print('Triggering firmware...')
send_command('M600')
# stop control
print('Ending control loop...')
send_command('M602', False)
print('Disconnected from printer, Firmware upload complete.')
print('You may need to restart your printer to complete the firmware update.')
except usb.core.USBError as error:
print('Firmware update failed, USB error:', error)
except Exception as error:
print('Firmware update failed, error:', error)
print()