Пишем плагин для Arduino IDE
- Войдите на сайт для отправки комментариев
Вс, 09/01/2022 - 22:58
Доброго дня, коллеги!
Я давно хотел написать что-нибудь про нашу IDE. В реальности очень любопытную конструкцию на JAVA.
В настоящей теме я закину "фидер" на леща. В том смысле, что приведу некий скелет плагина для IDE. Посмотрю "придет ли к берегу рыба". То есть вообще интересно это или народ быстро бросает IDE, переходя на более совершенные среды разработки?
Продолжу. Разработчики IDE оставили общий интерфейс создания собственных плагинов к среде. Пример лежит в ./tools/Mangler вместе с устаревшим сценарием Линукс shell для компиляции и сборки в jar.
При наличии минимальных знаний о JAVA можно поправить сценарий, переделать под Винду, если кому надо, и собрать Манглер - смешную игрушку перемешивающую выделенный фрагмент в открытом скетче.
Я пока нарочно не стану ничего писать о подробностях.
Вот так под свежую среду переписывается make.sh в Линуксе:
Виндоус версия - читателю, если кто заинтересуется.
После отработки мейк файла получается каталог ./tools/Mangler/tool, в котором лежит jar файл с плагином.
Пара слов о том, как писать плагины. Образец - манглер и плагины для записи файловых систем в ESP6266 и ESP32. Желательно использовать jar библиотеки уже имеющиеся в Arduino IDE. Во избежании глюков и несовместимостей. Наша ИДЕ вообще довольно любительская среда с большим количеством слабо написанного кода, хотя строк в исходнике на джаве - много тысяч.
Но следует признать, что ошибки понемногу удаляют и библиотеки есть почти на всё.
Главное, что нас может интересовать - библиотка работы с COM-портом -JSSC - она есть, конечно!
Ниже приведу не комментированный, совершенно сырой код для демонстрации возможностей плагинов.
Я писал "рыбу" для работы с ком-портом. Например можно придумать графики, стрелочные индикаторы, имитацию семисегментника или 12864. Да что угодно. Вывести два, три, четыре компорта, если нужно и так далее.
Для этого нужно научиться делать три вещи:
1. выбирать порт;
2. принимать данные;
3. Рисовать интерактивно в канве.
В приведенном коде есть все три компоненты. Повторю - нет комментариев. Код запускался на Линуксе и Вин10-64 (ВиртБокс). На Винде не собирал, а просто jar копировал из Линукса. Есть какие-то мелкие глюки в Винде, анализировать которые пока не интересно. Возможно особенности java-swing/awt на винде.
Сейчас меня интересует на вылизывание кода, тут не форум по java, а наличие интереса.
Будет интерес - продолжу. Заодно и виндовые темы разберу, или на форуме виндусятник найдется для помощи. Я все таки совершенно линуксовый человек. Винда для меня чужой и пугающий мир! ;)))
------------------------------------
Фсё! Наболтался, теперь код и мейк фал для сборки. От мейк файла манглера отличается только добавкой поиска jssc библиотеки.
код
package com.wlad.test001; import jssc.SerialPort; import jssc.SerialPortException; import jssc.SerialPortList; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.border.BevelBorder; import java.awt.*; import java.awt.geom.Ellipse2D; import java.util.ArrayList; import java.util.Arrays; import static java.awt.Color.RED; import static java.awt.Color.WHITE; import static javax.swing.WindowConstants.EXIT_ON_CLOSE; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.JOptionPane; import processing.app.Editor; import processing.app.tools.Tool; public class WladTest implements Tool { Editor editor; public void init(Editor editor) { this.editor = editor; } public String getMenuTitle() { return "Wlad Test"; } boolean isRunning = false; JFrame a = new JFrame("Влад тест"); JPanel p0 = new JPanel(); JPanel p1 = new JPanel(); DrawArea pg = new DrawArea(); JTextArea t = new JTextArea(12,60); JButton b = new JButton("START"); JButton b1 = new JButton("Rescan"); DefaultListModel<String> lm = new DefaultListModel<>(); JList<String> l = new JList<>(lm); SerialPort serialPort; boolean serialSet = false; public void run() { scanSerialPorts(); b.addActionListener(e -> { if (isRunning) { isRunning = false; b.setText("START"); } else { setSerialPort(String.valueOf(l.getSelectedValue())); isRunning = true; b.setText("STOP"); } }); b1.addActionListener(e -> scanSerialPorts()); t.setBounds(0,0,380,40); l.setBounds(0,0,380,100); b.setBounds(0,0,200,50); b1.setBounds(0,0,200,50); p0.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); p0.setBounds(0,0,790,190); p0.setLayout(new BorderLayout()); p0.add(new JScrollPane(t),BorderLayout.WEST); p0.add(b,BorderLayout.EAST); p1.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); p1.setBounds(0,0,790,190); p1.setLayout(new BorderLayout()); p1.add(b1,BorderLayout.EAST); p1.add(l,BorderLayout.WEST); pg.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); pg.setBounds(0,0,400,200); a.setSize(800,400); a.setLayout(new BorderLayout()); a.add(p0, BorderLayout.NORTH); a.add(p1, BorderLayout.SOUTH); a.add(pg, BorderLayout.CENTER); a.setVisible(true); } private static class DrawArea extends JPanel { ArrayList<int[]> points = new ArrayList<>(); public DrawArea () { setPreferredSize(new Dimension(400, 400)); } void add (int x, int y) { points.add(new int[]{x, y}); repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); setBackground(WHITE); Graphics2D g2d = (Graphics2D) g; g2d.setColor(RED); for (int[] p : points) { g2d.fill(new Ellipse2D.Double(p[0], p[1], 10, 10)); } } } public void scanSerialPorts () { lm.removeAllElements(); for (String pn : SerialPortList.getPortNames()) { lm.addElement(pn); } l.setSelectedIndex(lm.getSize()-1); l.ensureIndexIsVisible(lm.getSize()-1); } public void setSerialPort(String portName) { if (serialPort != null && serialSet) { try { serialPort.closePort(); } catch (SerialPortException ex) { ex.printStackTrace(); } } serialPort = new SerialPort(portName); try { serialPort.openPort(); serialPort.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.addEventListener(serialPortEvent -> { if (isRunning && serialPortEvent.isRXCHAR() && serialPortEvent.getEventValue() > 0) { try { String data = serialPort.readString(serialPortEvent.getEventValue()); // t.append(String.format("%s %20x\n", data, new BigInteger(1, data.getBytes(StandardCharsets.UTF_8))) + "\n"); // t.append(String.format("%s", data)); String[] xy = data.split(" "); int x = 0; int y = 0; try { x = Integer.parseInt(xy[0]); y = Integer.parseInt(xy[1]); } catch (NumberFormatException ex) { ex.printStackTrace(); } t.append(Arrays.toString(xy) + "\n"); pg.add(x,y); } catch (SerialPortException ex) { ex.printStackTrace(); } } }, SerialPort.MASK_RXCHAR); serialSet = true; } catch (SerialPortException ex) { ex.printStackTrace(); } } }Ну и мейк к нему
ПОнятно, что для отладки метод run() со-товащи нужно перепаковать в другой класс. Есть еще способы отладки, но это самый простой. У меня есть класс в IntelliJ IDEA в который я просто копирую кусок текста и обратно.
Снова напомню моё мнение о том, что писать на джаве (я всегда говорю "на яве") нужно исключительно в ИДЕЕ, не в Эклипсе и не в Нетбиинсе. Один раз запустив ИДЕЮ никогда к старому говну не вернешься. Ну как бы ИМХО. Хотя могу и принять пару лопаток на вентилятор! ;)
вопросик, может глупый - нафига работу с компортом и всякую графику к нему писать на яве, если есть процессинг, не говоря уж о более серьезных С++ средах. типа Qt ?
в чем преимущество этих "плагинов"?
Или я ничего не понял
я тоже.
я тоже.
не отлынивай! осталось определиться, а чего еще от IDE надо, я то ничего другого кроме IDE не видел, мнения быть не может )))
в чем преимущество этих "плагинов"?
Или я ничего не понял
Приходит к пластическому хирургу мужик и просит:
- Пришейте мне член ко лбу.
Доктор с крайней степенью удивления:
- Зачем??
- Ну во первых это красиво...
я тоже.
По порядку.
1. Куча народа. по моему мнению. может и не так, пользуется ИДЕ. Многие пользуются монитором порта при отладке. хоть он и кривее турецкой сабли.
2. Плагин в ИДЕ дает доступ к скетчу, вот прям к страничке в редакторе, в оранжевым буквам на черном фоне ;)) внизу, под редактором, ко всем настройкам платы. Что удобно, особенно для начинающего.
3. Плагин один раз закинул в папку со скетчами, как и платформы или библиотеки и не нужно пересталять вместе с ИДЕ. Ну по крайней мере пока не будет революционных изменений в ИДЕ ;))) Например перехода с 8 JDK на 11 ;))))) Гы! (это шутка для понимающих в яве)
4. Работа с портом просто мне интересна была, у меня всякие идеи на разбивку одного порта на виртуальные каналы в голове крутятся, но плагин это гораздо больше. Например можно написать конвертер картинок в массив для дисплея, который прямо в текст скетча напишет готовый код картинки. Доступ к редактору, напоминаю.
5. Ну и плагин же сам ложится в меню ИДЕ и оттуда вызывается, это удобно вообще.
-------------------
Если кто не понял, то я не призываю новичка учить яву, ява вообще язык ни разу не проще С. И не дает возможности писать без ООП, как на Ардуинке ;)). Мой призыв направлен к программистам, которых есть много на форуме! Писать интересные плагины. Для диагностики вместо монитора, для конвертации фонтов и картинок, да хоть для "замены делей на миллис", хоть это уже и иной уровень! ;))
Если для себя, то люди пишут инструменты отладки и проверки на привычном языке. Конечно на Питоне легче написать приблуду для ком порта. Но и Ява дает много. А главное, что по умолчанию Ява есть везде, а Питон только на Линуксе и Маке. Винда активно свой говноязык C# продвигает. Тот же Питон, только свой, виндовый, Никому нахер не нужный без активного пресса от Микрософт.
--------------------
Ну вот. я снова не удержался от пафоса и говнометания.... сорри. ;)) хотя, если честно, то пофигу.
Забавная тема. Если бы ещё не лень ... было у меня пара идей, что из этого можно сделать, но лениво, хотя и прикольно.
Женя! Ты пиши, может мне что понравится и я сделаю
Нет, ну там совсем ... скажем так, полезность
вызывает вопр...вернее, не вызывает вопросов, но прикольно :-)Общая идея - корёжить исходник:
1)
сделать более продвинутый препроцессор, тогда "библиотеки" можно разворачивать до констант, ставить только нужные куски кода и т.п.
2)
делать полную замену кода (кросс-компиляцию), чтобы например, можно было писать в IDE сразу на обобщённом брейнфаке, а вызов интерпретатора сам бы подставлялся.
Нет, ну там совсем ... скажем так, полезность
вызывает вопр...вернее, не вызывает вопросов, но прикольно :-)Общая идея - корёжить исходник:
Ну есть ограничения в самой среде. К редактору редакторский доступ ;). В том смысле, что в открытом документе можно что-то поменять. но заставить открыть в среде не ino/cpp/h/c нереально этим способом. Хотя никто не мешает открыть для редактирования своё окно, не штатного эдитора, а обычное, диалоговое. И в нем делать что-то на брейнфаке. создав потом заполнение для ino окна в ИДЕ.
А вот с препроцессором не сильно ясно. Это отдельный код. Можно всегда сделать некое свое ядро, в котором добавить свою обработку исходников и свои platform.txt и boards.txt. Но это немного другая тема выйдет.
Может и другая, я так подробно, как ты не разбирался. Просто идея была по аналогии с "добавить свой шаг в тулчейн вижуалстудии".
шаг можно добавить любой, ИДЕ очень гибкая, никто не заставляет использовать их препроцессор, но задача видится мне не в написании своего ИДЕ. а в мелких плагинах, которые не нужно заново ставить при обновлении ИДЕ. Например свой способ сборки, включая препроцессор, можно написать делая свое ядро. ну как всякие мини и микро коры.Инструмент плагинов это про работу с текстом в ОТКРЫТОМ редакторе и с подключенной платой. С брейнфаком весело можно сделать. ino будет генериться автоматом. ;))