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_() )