Skip to content

Commit e67c051

Browse files
Merge pull request #12 from OpenAstroTech/bugfix/js/11-avrdude-stderr-fix
Redirect avrdude output to file, watch the file and output to log
2 parents 53c1275 + 63fb8ab commit e67c051

File tree

3 files changed

+69
-7
lines changed

3 files changed

+69
-7
lines changed

OATFWGUI/external_processes.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import sys
22
import logging
3-
from typing import List, Dict, Optional
3+
from typing import List, Dict, Optional, Callable
44
from pathlib import Path
55

6-
from PySide6.QtCore import Slot, QProcess, QStandardPaths
6+
from PySide6.QtCore import Slot, QProcess, QStandardPaths, QProcessEnvironment
77

88
log = logging.getLogger('')
99

@@ -19,11 +19,19 @@ def __init__(self, proc_name, base_args):
1919

2020
self.qproc: Optional[QProcess] = None
2121

22-
def start(self, extra_args: List[str], finish_signal: Optional):
22+
def start(self, extra_args: List[str], finish_signal: Optional[Callable],
23+
env_vars: Optional[Dict[str, str]] = None):
2324
self.qproc = QProcess()
2425
self.qproc.setProgram(self.proc_name)
2526
self.qproc.setArguments(self.base_args)
2627

28+
proc_env = QProcessEnvironment.systemEnvironment()
29+
if env_vars:
30+
for k, v in env_vars.items():
31+
proc_env.insert(k, v)
32+
log.debug(f'Process environment:{proc_env.toStringList()}')
33+
self.qproc.setProcessEnvironment(proc_env)
34+
2735
# signals
2836
self.qproc.readyReadStandardOutput.connect(self.handle_stdout)
2937
self.qproc.readyReadStandardError.connect(self.handle_stderr)
@@ -33,7 +41,7 @@ def start(self, extra_args: List[str], finish_signal: Optional):
3341
self.qproc.setArguments(all_args)
3442
if finish_signal is not None:
3543
self.qproc.finished.connect(finish_signal)
36-
log.info(f'Starting {self.proc_name} with args: {all_args}')
44+
log.info(f'Starting {self.proc_name} with args: {all_args} and env {env_vars}')
3745
self.qproc.start()
3846
# Not sure why, but the process doesn't start without these
3947
proc_started = self.qproc.waitForStarted(10 * 1000)

OATFWGUI/gui_logic.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import requests
1313

14-
from log_utils import LogObject
14+
from log_utils import LogObject, LoggedExternalFile
1515
from qt_extensions import Worker, QBusyIndicatorGoodBad, BusyIndicatorState
1616
from external_processes import external_processes, get_install_dir
1717
from gui_state import LogicState, PioEnv, FWVersion
@@ -95,6 +95,9 @@ def __init__(self, main_app: 'MainWidget'):
9595
# Manually spawn a worker to refresh serial ports
9696
self.spawn_worker_thread(self.refresh_ports)()
9797

98+
# Need to create in the main thread else it doesn't work?
99+
self.avr_dude_logwatch = LoggedExternalFile()
100+
98101
def spawn_worker_thread(self, fn):
99102
@Slot()
100103
def worker_thread_slot():
@@ -298,6 +301,16 @@ def upload_fw(self):
298301
log.error(f"platformio already running! {external_processes['platformio']}")
299302
return
300303

304+
# Stupid fix for avrdude outputting to stderr by default
305+
if self.logic_state.pio_env is not None and any(
306+
avr_env_substr in self.logic_state.pio_env.lower()
307+
for avr_env_substr in ['mksgenl', 'ramps']):
308+
avrdude_logfile_name = self.avr_dude_logwatch.create_file(file_suffix='_avrdude_log')
309+
# Note: avrdude doesn't strip the filename! So no spaces at the beginning
310+
env_vars = {'PLATFORMIO_UPLOAD_FLAGS': f'-l{avrdude_logfile_name}'}
311+
else:
312+
env_vars = {}
313+
301314
external_processes['platformio'].start(
302315
['run',
303316
'--environment', self.logic_state.pio_env,
@@ -307,11 +320,13 @@ def upload_fw(self):
307320
'--upload-port', self.logic_state.upload_port,
308321
],
309322
self.pio_upload_finished,
323+
env_vars=env_vars,
310324
)
311325

312326
@Slot()
313327
def pio_upload_finished(self):
314328
log.info(f'platformio upload finished')
329+
self.avr_dude_logwatch.stop()
315330
exit_code = external_processes['platformio'].qproc.exitCode()
316331
if exit_code == 0:
317332
log.info('Normal exit')

OATFWGUI/log_utils.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import os
44
import enum
55
import html
6+
import tempfile
67
from pathlib import Path
78
from datetime import datetime
8-
from typing import Tuple
9+
from typing import Tuple, Optional
910

10-
from PySide6.QtCore import Signal, QObject
11+
from PySide6.QtCore import Slot, Signal, QObject, QFileSystemWatcher, QFile
1112

1213
from external_processes import get_install_dir
1314
from platform_check import get_platform, PlatformEnum
@@ -75,6 +76,44 @@ def format(self, record):
7576
return log_str
7677

7778

79+
class LoggedExternalFile:
80+
def __init__(self):
81+
# Don't want to global the `log` variable here (idk if things will break)
82+
self.log = logging.getLogger('')
83+
84+
self.file_watcher = QFileSystemWatcher()
85+
self.file_watcher.fileChanged.connect(self.file_changed)
86+
87+
self.tempfile: Optional[tempfile.NamedTemporaryFile] = None
88+
89+
def create_file(self, file_suffix: str = '') -> Optional[str]:
90+
self.tempfile = tempfile.NamedTemporaryFile(mode='r', suffix=f'{file_suffix}', delete=False)
91+
self.log.debug(f'Logging external file {self.tempfile.name}')
92+
93+
watch_success = self.file_watcher.addPath(self.tempfile.name)
94+
if not watch_success:
95+
self.log.warning(f'Could not watch external file: {self.tempfile.name}')
96+
return None
97+
return self.tempfile.name
98+
99+
@Slot()
100+
def file_changed(self, _path: str):
101+
lines = self.tempfile.readlines()
102+
for line in lines:
103+
if 'error' in line.lower():
104+
self.log.error(line)
105+
else:
106+
self.log.info(line)
107+
108+
def stop(self):
109+
self.log.debug(f'Cleaning up logged external file {self.tempfile.name}')
110+
self.tempfile.close()
111+
self.file_watcher.removePath(self.tempfile.name)
112+
remove_ok = QFile.remove(self.tempfile.name)
113+
if not remove_ok:
114+
self.log.warning(f'Could not remove temp file {self.tempfile.name}')
115+
116+
78117
def setup_logging(logger, qt_log_obj: LogObject):
79118
logger.setLevel(logging.DEBUG)
80119
# file handler

0 commit comments

Comments
 (0)