1. Введение
Большинство экранов LinuxCNC имеют возможность отправлять загруженные файлы через filter program или использовать программу-фильтр для создания G-кода. Такой фильтр может выполнять любую желаемую задачу: что-то простое, например проверка того, что файл заканчивается на «M2», или что-то более сложное, например создание G-кода из изображения.
2. Настройка INI для программных фильтров
Раздел [FILTER] INI-файла управляет работой фильтров. Сначала для каждого типа файла напишите строку PROGRAM_EXTENSION. Затем укажите программу, которая будет выполняться для каждого типа файла. Этой программе присваивается имя входного файла в качестве первого аргумента, и она должна записать код rs274ngc в стандартный вывод. Этот вывод будет отображаться в текстовой области, просматриваться в области отображения и выполняться LinuxCNC при нажатии кнопки Run. Следующие строки добавляют поддержку конвертера image-to-gcode, включенного в LinuxCNC:
[FILTER] PROGRAM_EXTENSION = .png,.gif Greyscale Depth Image png = image-to-gcode gif = image-to-gcode
Также возможно указать интерпретатор:
PROGRAM_EXTENSION = .py Python Script py = python
Таким образом, любой скрипт Python может быть открыт, а его выходные данные обрабатываются как G-код. Один из таких примеров скрипта доступен по адресу nc_files/holecircle.py. Этот скрипт создает G-код для сверления серии отверстий по окружности.
Если программа фильтра отправляет в stderr строки вида:
FILTER_PROGRESS=10
Он установит индикатор выполнения экрана на заданный (в данном случае 10) процент. Эту функцию следует использовать любому фильтру, работающему в течение длительного времени.
3. Создание программ фильтров на основе Python
Here is a very basic example of the filtering mechanics: When run through a Linucnc screen that offers program filtering, it will produce and write a line of G-code every 100th of a second to standard output. It also sends a progress message out to the UNIX standard error stream. If there was an error it would post an error message and exit with an exitcode of 1.
import time import sys for i in range(0,100): try: # simulate calculation time time.sleep(.1) # output a line of G-code print('G0 X1', file=sys.stdout) # update progress print('FILTER_PROGRESS={}'.format(i), file=sys.stderr) except: # This causes an error message print('Error; But this was only a test', file=sys.stderr) raise SystemExit(1)
Вот похожая программа, но она действительно умеет фильтровать. Она открывает диалоговое окно PyQt5 с кнопкой отмены. Затем она считывает программу построчно и передает ее на стандартный вывод. По ходу дела она обновляет любой процесс, прослушивающий стандартный вывод ошибок.
#!/usr/bin/env python3 import sys import os import time from PyQt5.QtWidgets import (QApplication, QDialog, QDialogButtonBox, QVBoxLayout,QDialogButtonBox) from PyQt5.QtCore import QTimer, Qt class CustomDialog(QDialog): def __init__(self, path): super(CustomDialog, self).__init__(None) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self.setWindowTitle("Filter-with-GUI Test") QBtn = QDialogButtonBox.Cancel self.buttonBox = QDialogButtonBox(QBtn) self.buttonBox.rejected.connect(self.reject) self.layout = QVBoxLayout() self.layout.addWidget(self.buttonBox) self.setLayout(self.layout) self.line = 0 self._percentDone = 0 if not os.path.exists(path): print("Path: '{}' doesn't exist:".format(path), file=sys.stderr) raise SystemExit(1) self.infile = open(path, "r") self.temp = self.infile.readlines() # calculate percent update interval self.bump = 100/float(len(self.temp)) self._timer = QTimer() self._timer.timeout.connect(self.process) self._timer.start(100) def reject(self): # This provides an error message print('You asked to cancel before finished.', file=sys.stderr) raise SystemExit(1) def process(self): try: # get next line of code codeLine = self.temp[self.line] # process the line somehow # push out processed code print(codeLine, file=sys.stdout) self.line +=1 # update progress self._percentDone += self.bump print('FILTER_PROGRESS={}'.format(int(self._percentDone)), file=sys.stderr) # if done end with no error/error message if self._percentDone >= 99: print('FILTER_PROGRESS=-1', file=sys.stderr) self.infile.close() raise SystemExit(0) except Exception as e: # This provides an error message print(('Something bad happened:',e), file=sys.stderr) # this signals the error message should be shown raise SystemExit(1) if __name__ == "__main__": if (len(sys.argv)>1): path = sys.argv[1] else: path = None app = QApplication(sys.argv) w = CustomDialog(path=path) w.show() sys.exit( app.exec_() )