1. Вступ
Більшість екранів LinuxCNC мають можливість надсилати завантажені файли через «програму фільтрації» або використовувати програму фільтрації для створення 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
Ось дуже простий приклад механізму фільтрування: при запуску через екран Linucnc, який пропонує фільтрування програм, він буде генерувати і записувати рядок G-коду кожні 100^-ті секунди в стандартний вивід. Він також надсилає повідомлення про хід виконання в стандартний потік помилок UNIX. У разі виникнення помилки він надсилає повідомлення про помилку і завершує роботу з кодом виходу 1.
import time import sys for i in range(0,100): try: # імітувати час обчислення time.sleep(.1) # вивести рядок G-коду print('G0 X1', file=sys.stdout) # прогрес оновлення print('FILTER_PROGRESS={}'.format(i), file=sys.stderr) except: # Це призводить до появи повідомлення про помилку 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() # обчислити відсотковий інтервал оновлення self.bump = 100/float(len(self.temp)) self._timer = QTimer() self._timer.timeout.connect(self.process) self._timer.start(100) def reject(self): # Це видає повідомлення про помилку print('You asked to cancel before finished.', file=sys.stderr) raise SystemExit(1) def process(self): try: # отримати наступний рядок коду codeLine = self.temp[self.line] # обробити рядок якось # виштовхнути оброблений код print(codeLine, file=sys.stdout) self.line +=1 # прогрес оновлення self._percentDone += self.bump print('FILTER_PROGRESS={}'.format(int(self._percentDone)), file=sys.stderr) # якщо виконано, завершується без помилки/повідомлення про помилку if self._percentDone >= 99: print('FILTER_PROGRESS=-1', file=sys.stderr) self.infile.close() raise SystemExit(0) except Exception as e: # Це видає повідомлення про помилку print(('Something bad happened:',e), file=sys.stderr) # це сигналізує про те, що має відображатися повідомлення про помилку 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_() )