
В прошлой статье я рассказал о своем подходе к разработке среды программирования промышленного контроллера — а именно о части, касающейся визуализации данных из цепей лестничных диаграмм и функциональных блоков, которые выполняются на стороне микроконтроллера. В этот раз подробнее остановлюсь на цепочке событий.
Как я уже упоминал, вся модель среды ПЛК (которую я разрабатываю) содержится в XML-файле. Этот файл включает в себя список функциональных блоков:
<LD_Unit Name="GTM" Group="Timer" Width="100" Height="55">

На основе этих данных среда (GUI-приложение на ПК) группирует блоки по вкладкам, используя тег <Group>. Внутри этих модулей (юнитов) также содержатся графические примитивы, которые определяют визуальный облик каждого блока.
<lists> <Item Type="RECT" color="#808080" Style="box" > <Value> </Value> <xy x="1" y="20" /> <dimension width="117" height="57" /> <stroke Stroke="1" /> <fill Fill="1" /> </Item>
Вся цепочка — от XML-строки до отрисовки блока на экране — выглядит следующим образом:

В параметры FBD-блоков я добавил тип Style="box". Теперь при очень длинных названиях в момент отрисовки функциональный блок автоматически расширяется под размер строки. Поначалу я хотел просто обрезать строки (как это сделано в типичных китайских средах разработки), но вовремя понял, что это небезопасно. Если элемент ссылается на поле сложной структуры — например, на элемент массива в самом конце строки, — то важную часть данных можно просто выпустить из виду, что неминуемо приведет к ошибкам:

После того как мы получили список примитивов, определяющих логику отрисовки функционального блока, мы применяем указанный в XML стиль. Происходит это непосредственно перед рендерингом примитива (в моем случае код написан на Java):
private void drawLine() { gc.setColor(AnimFabric.parseColor(color)); if(Style!=null && sm!=null) { if(Style.contains("onoff")) { gc.setColor(AnimFabric.onOff(sm.getValue(),Style)); } } Graphics2D g2d = (Graphics2D) gc; g2d.setStroke(new BasicStroke((float) stroke.Stroke)); g2d.drawLine((int) xy.x+X, (int) xy.y+Y, (int) x2y2.x+X, (int) x2y2.y+Y); }
Класс AnimFabric содержит типы анимации, а объект sm — тег и данные, привязанные к этому примитиву.
Первоначально я хотел сделать среду более современной, но затем расставил приоритеты в пользу легковесности. Для этого я использовал стандартные классы OpenJDK — как для отрисовки графики, так и для дизайна GUI в целом. В итоге среда спокойно запускается даже на ранних версиях Raspberry Pi и требует всего 120–200 МБ ОЗУ. Таким образом, из слабого мини-ПК можно сделать полноценный самопрограммируемый промышленный контроллер.
Так же, еще раз процесс работы из прошлого поста:
ссылка на оригинал статьи https://habr.com/ru/articles/1103386/