Содержание
Здесь содержится архив новостей пакета crwdaq.
Имеется также:
По предложению Н.Г. и других коллег в окне мнемосхем сделана возможность размещения заголовочных надписей на Панели Инструментов мнемосхемы, чтобы эффективно использовать свободное место.
Заголовочные надписи следует считать частью декорации окна мнемосхемы. Заголовочные надписи не являются сенсорами (не передаются в программу для обработки), но отображают постоянную надпись (типа названия прикладной системы) и могут содержать команду обработки, которая пересылается в главную консоль при нажатии мышью.
В секции [Circuit] описания мнемосхем добавлены два параметра:
Общий формат ():
ToolBarHeader = Width, "Header", Font, "Command", "Hint"
ToolBarLegend = Width, "Legend", Font, "Command", "Hint"
Например: см. demo_dim_ping dim_ping_main_ctrl.crc:
[Circuit]
GeneralMap = ..\Bitmaps\dim_ping_main_ctrl.bmp
Hint = Панель управления DIM_PING
ToolBarHeight = 2
ToolBarHeader = 170, "Демо DIM_PING", Name:PT_Sans\Size:16\Color:Navy\Style:[Bold], "@silent @daq devpost &DIM_PING.MAIN.CTRL @BrowseHelp", "Демонстрационная конфигурация DIM_PING"
ToolBarLegend = 180, "Тест скорости DIM", Name:PT_Sans\Size:12\Color:Blue\Style:[Bold], "@silent @daq devpost &DIM_PING.MAIN.CTRL @BrowseHelp", "Тест производительности DIM сервера"Введение этих заголовочных надписей полезно:
Можно сэкономить место на основном поле мнемосхемы.
Название прикладной системы можно поместить в заголовочной
надписи.
Можно поместить вызов справки в команду заголовочной
надписи.
Тогда по нажатию надписи будет открываться справка по прикладной
системе.
По предложению Н.Г. и других коллег в окне мнемосхем
сделана возможность скрыть кнопки стрелок для прокрутки изображения
мнемосхемы в окне, которые находятся в окне на Панели
Инструментов:
![]()
Во-первых, есть возможность делать это через меню Вид/Сдвиг изображения.
Во-вторых, это можно сделать через опции windraw с именами +/-ViewScrollLeft,ViewScrollRight,ViewScrollUp,ViewScrollDown.
Например, в конфигурации StartupScript можно использовать что-то вроде:
# Рисовать окно мнемосхемы
@WinShow DIM_PING.MAIN.CTRL
@WinDraw DIM_PING.MAIN.CTRL|Left=0|Top=0|Width=700|Height=800|Options=-Left,-Top,-Width,-Height
@WinDraw DIM_PING.MAIN.CTRL|Options=-Min,-Max,-Close,-HScroll,-VScroll,+StatusBar
# Спрятать кнопки прокрутки изображения
@WinDraw DIM_PING.MAIN.CTRL|Options=-ViewScrollLeft,-ViewScrollRight,-ViewScrollUp,-ViewScrollDownПри скрытии кнопок сдвига изображения их функции и горячие кнопки Shift+Стрелки остаются доступными.
Вернуть кнопки сдвига изображения можно горячими кнопками Ctrl+Стрелки.
Новые опции протестированы на demo_dim_ping, см. файл dim_ping_main_init.cfg.
Исправлена (указанная Н.Г.) досадная ошибка в
документации - константы tag_type_xxx.
В старой (ошибочной) версии была опечатка: type_tag_nil
вместо правильного tag_type_nil и т.д.
В диалоге СПИСОК ТЕГОВ, как было замечено Н.Г., при редактировании строкового тега результат приводился к верхнему регистру (а ожидаемое поведение - без изменения регистра). Кроме того, в строке обрезались пробелы (Trim), что также может быть нежелательным. Сейчас это исправлено и строка после редактирования передается “как есть”. Поэтому будьте внимательнее при редактировании.
Редактирование тегов через диалог СПИСОК ТЕГОВ
является неосновным (отладочным) средством,
тем не менее иногда используется разработчиками. Теперь оно должно
работать корректно.
Лишнее диалоговое окно заменено (по предложению Н.Г.) на всплывающее уведомление.
Заведена папка todo. В ней будут сохраняться модули или ссылки на проекты, которые хотелось бы зафиксировать, чтобы в будущем добавить в пакет. Пока это модули поддержки арифметики с повышенной точностью/разрядностью. Просто чтобы не потерялись.
В пакет добавлена библиотека изображений pictures от
Н.Г.
При добавлении было решено принять её “как есть”, с минимальными
правками (в документации).
Библиотека также добавлена в список изображений, используемых
в пакете crwdaq.
Для целей пакета взяты изображения .png с
дополнительной (пере)нумерацией для индексации изображений в
массиве.
Было замечено, что некоторые сообщения об ошибках DAQ системы “обрезаны”. Это связано с тем, что в DAQ системе для ошибок, зарегистрированных с помощью RegisterErr, использовался тип String[63] с длиной строк не более 63 символа (точнее, байта). Проблема возникла из-за того, что при переходе к строкам UTF8 максимальная длина строки понизилась, т.к. в кодировке UTF8 символы богут занимать больше одного байта, а размер буфера задан в байтах. Русские символы, например, занимают 2 байта, поэтому длина текста снижается до 31 символа UTF8.
Проблема решилась заменой типа строк на LongString с
неограниченной длиной.
Потребовались небольшие изменения кода.
Некоторые сообщения об ошибках были изменены на более понятные и точные.
В стандартную библиотеку добавились процедуры вывода:
Disturb -
“вызывающий беспокойство” - аналог Problem,
но с уровнем значимости severity гарантированно ниже
порога по умолчанию. То есть:
ошибку не генерирует, в журнал не пишется (как информация), в консоль
(при наличии флага) выводится.
Служит для вывода ошибок/проблем низкого уровня значимости, которые не
должны попадать в системый журнал
при стандартном уровне порога записи в журнал.
Alerter -
“предупредительный сигнал” - аналог Problem,
но с уровнем значимости severity гарантированно выше
порога по умолчанию. То есть:
ошибку не генерирует, в журнал пишется (как предупреждение), в консоль
(при наличии флага) выводится.
Служит для вывода ошибок/проблем среднего уровня значимости, которые
должны попадать в системый журнал
при стандартном уровне порога записи в журнал.
CritErr -
“критическая ошибка” - аналог Trouble,
но с уровнем значимости severity выше, чем у
Trouble. То есть:
ошибку генерирует, в журнал пишется (как критическая ошибка), в консоль
(при наличии флага) выводится.
Служит для вывода ошибок/проблем критического уровня значимости, которые
должны попадать в системый журнал
при стандартном уровне порога записи в журнал.
Fatally -
“это фатально” - аналог Trouble,
но с уровнем значимости severity выше, чем у
CritErr. То есть:
ошибку генерирует, в журнал пишется (как фатальная ошибка), в консоль
(при наличии флага) выводится.
Служит для вывода ошибок/проблем очень фатального уровня значимости,
которые обязаны попадать в системый журнал
при стандартном уровне порога записи в журнал.
Reports -
“отчитываюсь, докладываю” - вывод одного из видов отчета
Trouble, Problem,
Success, Succeed,
ViewImp, ViewExp,
Details,
Disturb, Alerter,
CritErr, Fatally. Тип отчета
указывается в первом слове,
например,
Reports('Success Всё в порядке.').
Процедура нужна для реализации команды
@Reports.
Причиной для введения дополнительных процедур послужило то, что хочется иметь короткие и потому удобные вызовы для вывода сообщений в консоль с генерацией ошибок или без, с разными уровнями значимости severity, с записью в журнал или нет.
Смотрите таблицу процедур вывода.
В стандартный обработчик добавлена команда
@Reports.
Например:
@Reports Success Успешно выполнено.
@Reports Trouble Возникла ошибка.Команда позволяет генерировать записи в консоль/журнал через посылку сообщений.
Утилита enca, с помощью которой определяется
кодировка файла, не всегда срабатывает.
Это вполне объективная трудность - не всегда удается статистически
надежно определить
кодировку, особенно для мелких файлов - решение может быть
неоднозначным, когда файл
может с большой вероятностью быть задан в одной из нескольких
кодировок.
В таких случаях утилита fixutf8zen отображает в меню
кодировку NONE.
В этом случае обработка таких файлов была невозможна, а файлы
игнорировались.
Сейчас в утилите fixutf8zen сделана возможность
выбора кодировки файлов,
для которых кодировка неизвестна, в ручном режиме (через меню).
В меню по умолчанию отмечен пункт WINDOWS-1251, т.к.
основная часть файлов
с неправильной кодировкой получена из Windows.
После выбора кодировки дополнительно спрашивается подтверждение, чтобы
исключить
возможность случайного выбора неверной кодировки.
Новая опция позволяет “лечить” кодировку для тех файлов, которые
раньше приходилось
“лечить” с помощью редакторов типа Notepad++, где есть
опция замены кодировки.
Это ускоряяет и облегчает процесс исправления кодировки файлов.
Теперь набор инструментов для поиска и исправления файлов с неверной (отличной от UTF8) кодировкой выглядит вполне завершенным.
Зввершена (в первом приближении) проверка и чистка каталогов crwdaq, crwkit, crwlib от файлов с неверной кодировкой (отличной от UTF8). Два последних каталога полностью “чистые”, а в каталоге crwdaq остаются файлы .odt, .cnt, .cmd, .dem, .dpr которые не надо конвертировать. Также несколько файлов .txt, .nsi, .pas от Windows-версий различных программ и от старой версии пакета crw32, которые тоже не требуется конвертировать.
В каталогах origami, kirigami есть
текстовые файлы (.js), которые не проходят тест на
UTF8.
Просьба к А.Ж. разобраться с этими файлами.
После появления рекурсивной версии утилиты проверки chkutf8 и fixutf8zen появилась возможность массированной проверки каталогов crwdaq, crwkit, crwlib.
По результатам проверки было найдено более сотни текстовых файлов с неправильной кодировкой, отличающейся от UTF8. Часть этих файлов в кодировке 1251 была пропущена “по недосмотру”. Другая группа файлов была отложена “на потом” по причине трудностей с переводом кодировки.
Дело в том, что НИ ОДНА из имеющихся программ как под Windows, так и под Linux не дает полной гарантии при (автоматическом) определении кодировки. Например, редактор Notepad++ под Windows довольно часто ошибается с кодировкой файлов, определяя, например, кодировку как Macintosh для файлов windows-1251. А программа enca, которая используется под Linux, в некоторых случаях не может надежно определить кодировку и выдает кодировку NONE в диалоге fixutf8zen. В этом случае приходится разбираться с файлами в ручном режиме. А это бывает довольно долго, особенно при большом числе файлов.
Была начата работа по “лечению” найденных файлов с неверной кодировкой.
Были переведены файлы с однозначно определяемой кодировкой - там, где это нужно. Часть файлов с кодировкой, отличной от UTF8, не требует перевода. Например, многие командные файлs .cmd, .bat не требуют изменения кодировки, т.к. они работают в среде оболочки Windows, которая не использует UTF8.
Часть файлов (пока еще) не переведена, т.к. файлов много и их обработка требует времени.
При переводе файлов выяснилось, что кроме определения “инвалидности” файлов очень полезно видеть строки, которые вызвали проблемы с UTF8.
Поэтому в утилиту fixutf8zen добавлен пункт меню checkv4 для того, чтобы выводить не только список “инвалидных” файлов, но и список строк, в которых найдены проблемы с форматом UTF8.
Это позволяет ускорить поиск проблемных файлов и проблемных строк с точки зрения формата UTF8.
В пакет crwkit добавлена утилита
unix chkutf8.
Она служит для проверки допустимости формата UTF8
текстовых файлов,
а также поиска текстовых файлов с неверной кодировкой (не
UTF8).
В отличие от утилиты fixutf8 она:
Например:
# Проверить файлы в текущем каталоге
unix chkutf8 .
# Проверить файлы в каталоге /etc не глубже 1 уровня рекурсии
unix chkutf8 -m1 /etcУтилита chkutf8 понадобилась потому, что утилита
fixutf8 не умеет работать
с каталогами и рекурсивным поиском. Поэтому для поиска недопустимых
UTF8
файлов в многоуровневых каталогах приходится много “лазить” по
каталогам
и искать в них файлы. Это порой отнимает много времени и чревато
ошибками.
А вдруг какой-то подкаталог забыли/пропустили и не проверили?
Утилита основана на вызове команды
cat filename | grep -vax '.*',
которая пропускает только строки, НЕ соответствующие
формату UTF8.
Остальное дело техники.
Модифицирована утилита fixutf8zen с учетом появления chkutf8.
В меню добавился пункт check, который позволяет
рекурсивно искать файлы
с неправильной кодировкой UTF8.
Поскольку эта утилита вмонтирована в панель команд Double
Commander,
то новая опция доступна в графическом режиме в Double
Commander.
Новая опция позволит облегчить поиск файлов с неправильной кодировкой
UTF8,
которые надо исправлять при переводе DAQ-конфигураций
из Crw32 в crwdaq.
Переведены под crwdaq некоторые драйверы demo_rs485proxy.
Все драйверы работают через штатный прокси-драйвер rs485proxy. Пока драйверы расположены локально (в демо-конфигурациях), но после отладки, вероятно, будут перемещены в системный каталог пакета.
Указанные драйверы, как минимум, запускаются (без ошибок в конфигурации) и как-то обмениваются данными. Тестирование проводилось на модулях другого типа, которые были под рукой, так что возможности полноценной проверки не было. Однако команды идентификации модулей проходят успешно, что говорит о верной работе прокси-драйвера RS485Proxy и цикла опроса.
Практически все драйверы требуют доработки - как минимум,
чистки кода и проверки на
аппаратуре.
Поэтому эти драверы пока приняты условно, как
экспериментальные.
Просьба членам команды DaqGroup (разработчикам драйверов - Эдуарду с коллегами) синхронизировать демо-версии драйверов со своими рабочими версиями и по возможности “довести до ума” указанные драйверы.
Участники DaqGroup (Эдуард и другие) начали работы созданию драйверов устройств на шине RS485 - в первую очередь серии I7000. Ключевым элементом этих драйверов станет прокси-драйвер &RS485Proxy, который нужен для сериализации (выстраивания в очередь) запросов драйверов устройств на шине RS485.
Этот драйвер был разработан на базе кода ModbusProxy как автономный код. Сейчас начат процесс интеграции этого кода в качестве штатного сервера crwdaq. Имеется справка rs485proxy.htm.
Состав прокси-драйвера:
Обратите внимание, что включаемые файлы в папке include сделаны как исмволические ссылки на исходные файлы в папке rs485proxy. Под Linux с этим нет проблем, а вот в версии под Windows это приведет к ситуации, когда будет две копии включаемых файлов, т.к. нормальной поддержки символических ссылок под Windows нет (используются симлинки с относительными путями). Если ничего не трогать, это не проблема. Но в случае редактирования под Windows появится две разные копии файлов. А это уже источник возможных проблем (какой из файлов правильный?). Это надо иметь в виду разработчикам.
Утилиты assoc, ftype, find-app немного доработаны. В них появилась опция –cmd для того, чтобы выполнять подстановку параметров и получать командную строку для запуска файла.
Например:
# Команда Exec для файлов *.txt
unix assoc -e .txt
.txt=kate -b %U
# Командная строка для файла test.txt
unix assoc -c .txt test.txt
.txt=kate -b test.txt
# Команда Exec для приложения markdownviewer
unix find-app -e markdownviewer-browse.desktop
markdownviewer %f --browse "firefox --new-tab"
# Командная строка для обзора readme.md
unix find-app -c markdownviewer-browse.desktop readme.md
markdownviewer readme.md --browse firefox --new-tab
# Команда Exec для файлов text/markdown
unix ftype -e text/markdown
text/markdown=markdownviewer %f --browse "firefox --new-tab"
# Командная строка для обзора readme.md
unix ftype -c text/markdown readme.md
text/markdown=markdownviewer readme.md --browse firefox --new-tabКак можно заметить, опция –cmd заменяет шаблоны %f, %F, %u, %U из параметра Exec (из файла ярлыка .desktop) на аргументы командной строки (начиная со второго позиционного параметра). В результате получается командная строка для запуска ярлыка с заданными аргументами. Это облегчает использование команд.
Утилиты assoc, ftype существенно доработаны.
# Список ассоциаций для файлов *.txt
unix assoc .html
.html=application/x-extension-html
.html=text/html
# Обработчик по умолчанию для файлов *.txt
unix assoc -d .html
.html=userapp-Firefox-SKMN42.desktop
# Список обработчиков для MIME типа text/html
unix ftype text/html
text/html=firefox.desktop
text/html=userapp-Firefox-97PF32.desktop
text/html=userapp-Firefox-SKMN42.desktop
# Обработчик по умолчанию для MIME типа text/html
unix ftype -d text/html
text/html=userapp-Firefox-SKMN42.desktop
# Иконка для MIME типа text/html
unix ftype -i text/html
text/html=firefox
# Список файлов иконок с именем firefox
unix find-icon firefox
/usr/share/icons/hicolor/48x48/apps/firefox.png
...
/usr/share/pixmaps/firefox.pngНадо отметить, что есть проблемы с производительностью утилиты
unix find-icon.
Поскольку в хранилище системы более 100 000 картинок, поиск занимает время. При первом пуске find-icon поиск занимает несколько секунд, при последующих вызовах - около 0.4 секунды (за счет кеширования файлов), что тоже довольно много.
Поиск можно существенно ускорить, если использовать файлы index.theme в каталогах поиска icons, однако это сильно усложнит код. Пока эта оптимизация оставлена на будущее.
Для справки:
Для запуска приложений, заданных ярлыком .desktop, есть три стандартные утилиты:
gtk-launch,xdg-open,gio launch.
В следующем примере запускается приложение dim-cpl.desktop.
# Способ 1 - Запуск через gtk-launch
# Передается короткое имя приложения
gtk-launch dim-cpl.desktop
# Способ 2 - Запуск через xdg-open
# Передается полное имя приложения,
# вычисляемое через вызов unix find-app
xdg-open $(unix find-app dim-cpl.desktop)
# Способ 3 - Запуск через gio-launch
# Передается полное имя приложения,
# вычисляемое через вызов unix find-app
gio launch $(unix find-app dim-cpl.desktop)Все эти способы запуска можно использовать в сценариях совместно с утилитами обработки файловых типов и ассоциаций unix assoc, ftype, find-app, find-icon.
Утилиты assoc, ftype существенно переработаны. Общий код вынесен в общий включаемый файл, чтобы исключить дублирование. Код почищен, поправлены обнаруженные ошибки.
Добавлена утилита find-app. Эта утилита служит для поиска файла ярлыка .desktop для обработчика приложения. Команда ftype выдает имя обработчика, но для различных целей может потребоваться найти полное имя файла, на который ссылается обработчик. Также команда позволяет извлечь для обработчика имя иконки Icon и выполняемую команду Exec.
Добавлена утилита find-icon. Эта утилита служит для поиска файла изображения (.png|.xpm|.svg) для иконки по имени.
Например:
# Узнать MIME тип файлов .lm9
unix assoc .lm9
.lm9=application/x-diesel
# Узнать обработчики для типа application/x-diesel
unix ftype application/x-diesel
application/x-diesel=CrossDesigner.desktop
application/x-diesel=CrossMachine.desktop
# Узнать файл обработчика CrossMachine.desktop
unix find-app CrossMachine.desktop
/usr/share/applications/CrossMachine.desktop
# Узнать командную строку Exec обработчика CrossMachine.desktop
unix find-app -e CrossMachine.desktop
/opt/diesel/CrossMachine %F
# Узнать имя иконки для обработчика CrossMachine.desktop
unix find-app -i CrossMachine.desktop
CrossMachine
# Узнать имя файла для иконки CrossMachine
unix find-icon CrossMachine
/usr/share/pixmaps/CrossMachine.pngПоскольку Рабочие Столы в Linux поддерживают темы theme и различные размеры иконок size, то команда find-icon может выдавать список одноименных файлов разных тем и размеров, а также имеет опции –theme, –size для выбора изображений, а кроме того, поддерживает маски (регулярные выражения) имен иконок, если нужно посмотреть иконки с заданным шаблоном имени.
Например:
# Список тем для иконок
unix find-icon --list
Icon Themes: Adwaita astra-proxima breeze breeze-dark fly-astra fly-astra-flat fly-astra-flat-black fly-astra-flat-white gnome hicolor HighContrast
# Файл иконки kate из темы breeze
unix find-icon --theme breeze kate
/usr/share/icons/breeze/apps/48/kate.svg
# Все файлы иконки kate с размером 48
unix find-icon --size 48 kate
/usr/share/icons/hicolor/48x48/apps/kate.png
/usr/share/icons/breeze/apps/48/kate.svg
/usr/share/icons/fly-astra-flat/48x48/apps/kate.png
/usr/share/icons/breeze-dark/apps/48/kate.svg
# Все файлы иконки kate с размером scalable (масштабируемая)
unix find-icon --size scalable kate
/usr/share/icons/hicolor/scalable/apps/kate.svg
# Все файлы масштабируемых иконок для диалогов
unix find-icon --size scalable 'dialog-*'
/usr/share/icons/Adwaita/scalable/status/dialog-question-symbolic.svg
/usr/share/icons/Adwaita/scalable/status/dialog-error-symbolic.svg
/usr/share/icons/Adwaita/scalable/status/dialog-information-symbolic.svg
/usr/share/icons/Adwaita/scalable/status/dialog-warning-symbolic.svg
/usr/share/icons/Adwaita/scalable/status/dialog-password-symbolic.svg
/usr/share/icons/HighContrast/scalable/actions/dialog-close.svg
/usr/share/icons/HighContrast/scalable/actions/dialog-cancel.svg
/usr/share/icons/HighContrast/scalable/actions/dialog-ok.svg
/usr/share/icons/HighContrast/scalable/status/dialog-password.svg
/usr/share/icons/HighContrast/scalable/status/dialog-question.svg
/usr/share/icons/HighContrast/scalable/status/dialog-error.svg
/usr/share/icons/HighContrast/scalable/status/dialog-information.svg
/usr/share/icons/HighContrast/scalable/status/dialog-warning.svg
# Узнать общее число иконок в системном хранилище
unix find-icon '*' | wc -l
111613Как видно из последнего примера, в типичной инсталляции может содержаться более сотни тысяч файлов изображений для иконок.
Поэтому в общем случае поиск иконки - сложный итерационный процесс, т.к. с одной стороны одноименных картинок может быть много (они могут отличаться размерами и темой), а с другой стороны файла с интересующим размером в заданной теме может не быть.
Поэтому рекомендуется:
Для поиска изображений в общем случае рекомендуется:
Программы DaqGroup при инсталляции кладут изображения в каталог /usr/share/pixmaps. Это место считается несколько устаревшим, т.к. сейчас обычно темы располагаются в каталоге /usr/share/icons. Однако каталог pixmaps тоже указан в спецификации (с пометкой “для совместимости”), поэтому является вполне стандартным местом для иконок, которые не поддерживают темы, т.е. выглядят одинаково для всех тем. Поэтому иконки программ DaqGroup следует искать без указания размера и темы.
На данный момент представляется, что команды unix assoc, ftype, find-app, find-icon дают достаточный набор средств для обработки файлов по расширению или MIME типу, а также для работы с иконками приложений.
Все перечисленные утилиты делались (по мере возможности) в согласии со спецификациями XDG.
С пакет crwkit добавлена утилита readini.
Эта утилита служит для чтения секций или
значений параметров из INI файла
“классического” формата. Классический формат предполагает, что секции
уникальны (т.е. в файле есть только одна секция с данным именем) и
непрерывны (текст секции не разбит на части, а идет одним блоком). Кроме
того, не поддерживается включение файлов через механизм
[ConfigFileList], как это принято в пакете
crwdaq. Другими словами, это простой формат
INI файлов в стиле Windows без
расширенных возможностей.
Например:
# Чтение секции [global] из файла smb.conf
unix readini /etc/samba/smb.conf "[global]"
# Чтение значения параметра "log file"
unix readini /etc/samba/smb.conf "[global]" "log file"
# Справка
unix readini --help
readini.sh version 1.0
readini.sh Copyright (c) 2025 Alexey Kuryakin daqgroup@mail.ru
Utility to read INI file section or parameter key=value.
Usage:
readini.sh [-options] [inifile section [keyname]]
Options:
--version - print version
-h,--help - print help screen
-i,--ign - ignore case: section/keyname is not case sensitive
-r,--rem c - set chars (c) for remark, default chars is -r '#;'
--raw - print raw section's text, don't remove space chars
Parameters:
inifile - (mandatory) INI file to read
section - (mandatory) section name to read
keyname - (optional) key name to read key=value
Notes:
1) By default section/keyname is case sensitive. Use option '-i' to ignore case.
2) By default remark starts with '#;' will drop. Use option '-r' to set remarks.
3) By default output lead and trail chars drop. Use option --raw to print AsIs.
4) Section''s text must be single-part and continuous, like standard Windows INI.
Use 'readcfg' instead for multi-part sections with [ConfigFileList] support.
Examples:
readini.sh --help
readini.sh --version
readini.sh -i -r '#' /etc/samba/smb.conf "[global]" "log file"
readini.sh /usr/share/applications/CrossMachine.desktop "[Desktop Action Edit]"
readini.sh /usr/share/applications/CrossMachine.desktop "[Desktop Action Edit]" ExecУтилита работает существенно (примерно в 5 раз)
быстрее более “продвинутой” программы
unix readcfg, которая читает
конфигурационные файлы с поддержкой расширенных возможностей. Она служит
для чтения простых INI файлов в сценариях, которым
нужны данные из INI файлов.
Утилита имеет дополнительные опции (регистронезависимые имена, задание символа комментария).
С пакет crwkit добавлена утилита ftype.
Утилита работает аналогично команде ftype под
Windows. Она печатает строку (или список строк)
mime=handler, где mime -
тип файла, а handler - обработчик для этого файла.
Для сведения:
*.desktop,unix ftype -p …
можно выводить полный путь файла обработчика.unix ftype -e …
можно выводить команду Exec, которая вызывается
обработчиком.gtk-launch handler.desktop [filename].Например:
# Узнать список обработчиков для MIME типов
unix ftype
application/csv=libreoffice-calc.desktop
application/excel=libreoffice-calc.desktop
... и так далее ...
# Узнать обработчик для MIME типа text/plain
unix ftype text/plain
text/plain=org.kde.kate.desktop
# Узнать путь для обработчика
unix ftype --path text/plain
text/plain=/usr/share/applications/org.kde.kate.desktop
# Узнать команду Exec для обработчика
unix ftype --exec text/plain
text/plain=kate -b %U
# Запустить полученный обработчик (просто)
gtk-launch org.kde.kate.desktop
# Запустить полученный обработчик (с указанием файла)
gtk-launch org.kde.kate.desktop $HOME/demo.txtУтилита ftype сделана согласно спецификации
XDG
Desktop Entry Specification.
Она будет полезна в сценариях для обработки файлов в зависимости от
MIME типа.
По этой спецификации в команде Exeс используются такие подстановки:
%f - Имя одного файла, даже если
выбрано несколько файлов.%F - Список файлов.%u - Один URL.%U - Список
URL-адресов.%i - Ключ Icon записи
рабочего стола расширяется в виде двух аргументов, сначала
–icon, а затем значения ключа Icon. Не
должен расширяться до каких-либо аргументов, если клавиша
Icon пуста или отсутствует.%c Переведенное имя приложения,
указанное в соответствующем ключе Name в записи
рабочего стола.%k Местоположение файла рабочего стола
либо в виде URI (если, например, получено из системы
vfolder), либо в виде локального имени файла или
пустого, если местоположение неизвестно.При использовании результата
unix ftype --exec … эти подстановки нужно
выполнять.
Теперь есть все средства для обработки файлов в зависимоти от их расширения.
Сочетание ftype и assoc позволяет узнать, какой тип MIME соответствует данному расширению имени файла и какой обработчик для него нужен.
В библиотеку crwlib добавлен модуль _crw_mimeglob. Этот модуль дает отображение расширений имен файлов в типы MIME под Linux, аналогично тому, как делает команда assoc под Windows.
Благодаря этому модулю:
ParamStr('ListOf assocs'),@list assocs.Модуль реализован в соответствии с спецификацией Shared MIME-info Database.
В окне Главная Консоль добавлена команда
@list assocs (точнее, добавлена опция
assocs).
@list assocs # Печатать список ассоциаций .ext=mime
@list assocs .txt # Печатать MIME тип для файлов *.txtВ функции ParamStr добавлена опция assocs:
list:=ParamStr('listof assocs'); // Список ассоциаций .ext=mime
mime:=ParamStr('listof assocs where name=.txt'); // MIME тип для файлов *.txtВ сборку crwkit добавлена утилита
unix assoc. Она работает аналогично
команде assoc в Windows. Но при этом
имеет расширенные возможности.
# Список ассоциаций .ext=MIME
unix assoc
.7z=application/x-7z-compressed
...
.zz=application/zlib
# Ассоциация MIME типа для файлов .txt
unix assoc .txt
.txt=text/plain
# Ассоциация ярлыка запуска .desktop для файлов .txt
unix assoc -d .txt
.txt=org.kde.kate.desktop
# Ассоциация исполняемого файла для файлов .txt
unix assoc -e .txt
.txt=/usr/bin/kate
# Ассоциация иконки для файлов .lm9
unix assoc -i .lm9
.lm9=CrossMachineУтилита служит для определения программ для обработки файлов по расширению этих файлов.
После введения функции wdt_timeout стало возможным решение проблемы срабатывания Watchdog в сервере &FdbSrv, которое наблюдается при создании новой базы данных для сохранения суточных данных. Эта операция может занимать больше стандартного времени ожидания сторожевого таймера - по умолчанию это 5 секунд. Решением является задание большего значения таймаута (например, 30 секунд) потоку сервера &FdbSrv для выполнения этой операции. Это можно проиллюстрировать таким псевдокодом:
procedure Polling; // В процедуре опроса
begin //
if NewDataBase then begin // Если надо создать новую БД
tm:=wdt_timeout(30000); // Задаем большой таймаут
bNul(wdt_reset(true)); // Сбрасываем Watchdog
CreateNewDataBase; // Не спеша создаем новую БД
iNul(wdt_timeout(tmt)); // Восстанавливаем таймаут
bNul(wdt_reset(true)); // Сбрасываем Watchdog
end;
... // Идем дальше
end;Теперь ложных срабатываний сторожевого таймера в сервере &FdbSrv быть не должно (во всяком случае при создании новой базы данных)
В сервер FdbSrv внесены поправки, связанные с правами доступа к папке данных под Linux. В предыдущих версиях сервера запись данных выполнялась через клиентскую библиотеку под текущим пользователем, поэтому вопроса с правами доступа не было. Сейчас при сохранении используется сервер (если он установлен), который работает под пользователем firebird, и он создает файлы под этим пользователем. Для работы сервера необходимо, чтобы он имел все права доступа к папке данных, где будут создаваться файлы. Поэтому папке данных надо предоставлять права drwxrwxrwx, чтобы сервер мог нормально работать. Если прав доступа не хватает, сервер выдает ошибку и запись в БД не происходит.
Использование сервера, хотя и требует проверки прав доступа, предпочтительнее использования клиентской библиотеки, т.к. позволяет просматривать базу данных в процессе работы - даже если в момент доступа к БД идет запись в базу данных. Эту возможность предоставляет сервер Firebird. Если же запись идет через клиентскую библиотеку, то файл БД блокируется на время записи и становится недоступным для чтения.
Выбор способа обращения к БД определяется строкой подключения. Если в строке подключения указан сервер (обычно localhost), то доступ к БД делается через сервер Firebird, при этом сервер обеспечивает параллельный доступ к БД для множества клиентов. Если в строке подключения сервер не указан, то доступ к БД делается через клиентскую библиотеку напрямую, при этом файл блокируется и становится недоступен.
В новой версии FdbSrv при каждой операции записи проверяются и при необходимости предоставляются требуемые права доступа к папке.
В DaqPascal добавлена функция wdt_timeout. Она задает время ожидания (таймаут) для стророжевого таймера данного устройства в миллисекундах. Значением таймаута по умолчанию является 0. Реальное время ожидания берется как максимальное из таймаута для данного устройства и системного таймаута, заданного в диалоге Сторожевой таймер.
Задание таймаута позволяет избежать ложной тревоги при запланированных длительных операциях.
Создан сценарий crwdaq.syslog.cmd (под Windows). Он вызывается (только) в контексте сессии crwdaq и служит для записи событий в журнал sys.log для текущей сессии из внешних программ. Также модифицировван сценарий crwdaqwatcher.cmd для записи статуса завершения работы сеанса под заголовком Session Outcome.
Тактим образом, теперь в журнале SysLog будет запись под заголовком Session Outcome о статусе завершения процесса crwdaq и результатах проверки утечки памяти.
Запись под заголовком Session Outcome о статусе завершения работы сеанса может иметь три варианта:
Такие записи будут полезны для анализа работы систем управления при длительной эксплуатации.
Создан сценарий crwdaq.syslog.sh. Он вызывается (только) в контексте сессии crwdaq и служит для записи событий в журнал sys.log для текущей сессии из внешних программ.
Например:
# Сообщение с передачей в аргументах
crwdaq.syslog.sh "INFO/NOTIFY: simply/crwdaq_1/System - Работа кипит.";
# Сообщение с передачей через канал
echo "INFO/NOTIFY: simply/crwdaq_1/System - Работа кипит." | crwdaq.syslog.sh;Предполагается, что сценарий будут использовать дочерние процессы сеанса crwdaq.
С помощью утилиты crwdaq.syslog.sh в программе crwdaqwatcher.sh добавлен отчёт под заголовком Session Outcome о завершении (нормальном, аварийном или проблеммном) процесса для сессии crwdaq.
Сценарий crwdaq.syslog.sh нужен потому, что отчёт о завершении сессии составляется уже после того, как процесс crwdaq завершился, поэтому запись в журнал нельзя выполнить посылкой сообщения в Главную Консоль, как делается в обычных случаях.
После долгих размышлений был зафиксирован набор уровней значимости severity:
0 DEBUG
1 DEBUG/REMARK
2 DEBUG/COMMENT
3 DEBUG/NOTICE
4 DEBUG/MARK
5 DEBUG/DETAILS
6 DEBUG/VIEWEXP
7 DEBUG/VIEWIMP
8 DEBUG/REPORT
9 DEBUG/ATTENTION
10 INFO
11 INFO/VOICE
12 INFO/TOOLTIP
13 INFO/INPUT
14 INFO/PRINT
15 INFO/NOTIFY
16 INFO/SUCCESS
17 INFO/SUCCEED
18 INFO/GREAT
19 INFO/PERFECT
20 WARN
21 WARN/WORRY
22 WARN/HAZARD
23 WARN/DISTURB
24 WARN/HARDSHIP
25 WARN/PROBLEM
26 WARN/MISTIMES
27 WARN/EXCEPTION
28 WARN/WATCHDOG
29 WARN/ALERT
30 ERROR
31 ERROR/BUG
32 ERROR/GLITCH
33 ERROR/FAIL
34 ERROR/FAULT
35 ERROR/TROUBLE
36 ERROR/ALARM
37 ERROR/DANGER
38 ERROR/SIREN
39 ERROR/CRITICAL
40 FATAL
41 FATAL/FAILURE
42 FATAL/ABORT
43 FATAL/CRASH
44 FATAL/MISFORTUNE
45 FATAL/EMERGENCY
46 FATAL/ACCIDENT
47 FATAL/CATASTROPHE
48 FATAL/DISASTER
49 FATAL/DOOMSDAY
50 OFFВозможно, таблица не вполне совершенна, многие названия и порядок уровней субъективны. Например, трудно решить, что важнее - fail или fault? Однако в целом эта таблица выглядит разумно и даже она потребовала довольно много времени и размышлений - так что будем её использовать.
Уровни значимости также перечислены в файле crwdaq.sever.ini с комментариями.
Доработана группа утилит unix cherry
(вишенка).
Это набор утилит содержит сценарии для работы с репозиторием,
обслуживания серверов и прочие служебные утилиты.
С помощью вызова unix cherry -m утилиты
можно вызывать в виде графического меню на основе
zenity.
Модифицирован алгоритм AwakeModalWindows службы слежения за модальными окнами.
Во-первых, добавлена проверка условия (MODAL and not HIDDEN) для активного окна на Рабочем Столе. Если это условие выполнено, т.е. активное окно модальное и не свернутое, то активизация модального окна crwdaq отменяется. Модальное окно crwdaq не требуется активизировать, т.к. на экране уже есть активное модальное окно. Эта проверка нужна для того, чтобы избежать конкуренции нескольких сеансов crwdaq за фокус ввода. Если один из сеансов уже получил фокус, он его сохраняет (пока открыто модальное окно).
Кроме того, изменен формат параметра AwakeModalWindowsFocus. Раньше это был просто флаг (1/0) для разрешения активизации модального окна, теперь это битовая маска, где бит 0 (1/0) имеет такой же смысл как и раньше, но добавляется бит 1, который означает флаг Glob (глобальный). Если выставлен глобальный флаг, то модальное окно будет активизироваться (“всплывать”) в глобальном контексте, т.е. среди всех окон (а раньше - только среди окон текущего процесса crwdaq).
Таким образом, модальное окно crwdaq активизируется, если:
Приведенный алгоритм призван, с одной стороны, более настойчиво “выталкивать” модальный диалог наверх, чтобы его было видно на экране, а с другой стороны, старается не допускать конкуренции приложений, одновременно открывших модальные диалоги, чтобы избежать путаницы.
Посмотрим, как это будет работать на практике.
Немного изменены (улучшены) настройки klogg.conf.
Изменения коснулись шаблонов для подсветки событий в журналах в зависимости от уровня значимости. Эти правки нельзя было внести раньше, пока не была зафиксирована таблица severity.
В частности, теперь события INFO/(SUCCESS|SUCCEED) подсвечиваются зеленым, а INFO/(GREAT|PERFECT) - ярко-зеленым.
Кроме того, кодировка по умолчанию изменена с
defaultView.encodingMib=-1
(AutoDetect) на
defaultView.encodingMib=106
(UTF-8). Это связано с тем, что автоматическое
определение кодировки не всегда срабатывает.
Создана и добавлена в сборку crwkit утилита
unix xmonsize (от X monitor
size), см. xmonsize.sh.
Она служит для определения размера экрана/монитора (в пикселях).
Например:
# Вся информация
unix xmonsize -a
Screen0: 1920 1080
Primary: 1920 1080
DISPLAY: :0
Monitor1: 1920 1080
Monitors: 1
# Список мониторов
unix xmonsize -l
Monitor1: 1920 1080
# Основной монитор
unix xmonsize -p
Primary: 1920 1080
# Список экранов
unix xmonsize -s
Screen0: 1920 1080Основное назначение утилиты - определение размеров экрана в сценариях bash. Например, для диалогов на основе zenity.
Утилита проверялась на том что есть (один монитор). Она нуждается в проверке на многомониторных системах.
Добавлена утилита crwdaqlogroll.cmd для ротации журналов под Windows.
Также вызов crwdaqlogroll.cmd добавлен в сценарий входа crwdaq.logon.cmd и выхода crwdaq.logout.cmd и наблюдения crwdaqwatcher.cmd.
Система ротации журналов проверена на примерах, которые генерируют
большой объем спама через процедуру Problem.
Вроде бы ротация журналов работает корректно под Linux
и Windows.
Сделано описание службы обслуживания журналов SysLog.
На сегодняшний момент система ротации журналов выглядит (в первом приближении) завершенной.
Добавлена утилита crwdaqlogroll.sh. Она
анализирует каталог журналов crwdaq и (при
необходимости) применяет утилиту
unix logroll к тем журнальным файлам,
которые выросли больше заданного предела (сейчас -
32MB).
Также вызов crwdaqlogroll.sh добавлен в сценарий входа crwdaq.logon.sh и выхода crwdaq.logout.sh.
Также вызов crwdaqlogroll.sh добавлен в сценарий слежения (наблюдения) crwdaqwatcher.sh, который обеспечивает вызов процедуры чистки (прокрутки) журналов примерно раз в минуту.
Остается сделать аналогичные вызовы для Windows.
Утилита logroll переведена под Windows - logroll.cmd.
К сожалению, под Windows работают только компрессоры gz,bz, а компрессоры xz,lz не работают.
Однако на практике будет использоваться компрессор по умолчанию gz, так что это не страшно.
Утилита logroll закрывает базовые потребности в ротации журналов или вообще версий файлов. Однако следует помнить, что logroll - простой автомат, выполняющий ротацию файлов без какой-либо проверки условий. За все проверки (например, ротация журналов по достижению определенного размера) отвечает вызывающий код. Утилита logroll лишь исполняет ротацию, когда её необходимость возникла.
В сценарий crwdaq.logon.cmd добавлен код валидации logroll, который копирует (обновляет) logroll.cmd в каталог %UnixRoot%/usr/local/bin.
Это надо для того, чтобы unix logroll работал в любом контексте под Windows.
Под Linux такой необходимости нет, т.к. logroll изначально встроен в crwkit.
Создана и добавлена в сборку crwkit утилита
unix logroll, см. logroll.sh.
Эта утилита осуществляет ротацию (roll или rotate) файлов, обычно журнальных. Она работает аналогично штатной программе logrotate, которая обслуживает системные журналы Linux. Нам она напрямую не подходит (долго объяснять почему), но принцип там заложен верный.
Пример:
# Вызов с явными параметрами
logroll -t demo.log 9 gz
# Ротирует журнал demo.log с 9 поколениями и сжатием gzip
# Сжатие применяется к 2-му и выше поколению копий журнала
# Опция -t (--touch) значит, что при ротации надо создать
# новый журнал нулевой длины
# Создает файлы:
# demo.log - новый текущий журнал нулевой длины
# demo.log.1 - старая копия журнала 1-го поколения
# demo.log.2.gz - сжатая копия журнала 2-го поколения
# demo.log.3.gz - сжатая копия журнала 3-го поколения
# ...
# demo.log.9.gz - сжатая копия журнала 9-го поколения
# Вызов с параметрами по умолчанию 9 gz
logroll -t demo.logУтилита ротации журнала будет применяться для обслуживания sys.log и других журналов crwdaq.
Введен параметр [System] StartupSysLogLevel. Это начальный (при загрузке) уровень триггера SysLog. Его установка нужна для вывода сообщений в момент загрузки, т.к. начальный уровень SysLog - по умолчанию OFF.
Исправлена обработка канала tty0, который отвечает за обработку ссобщений send2crwdaq.
Проблемы было две:
Сейчас это исправлено.
В журнал SysLog теперь пишется результат проверки целостности основных файлов пакета.
Проверка выполняется в сценариях входа/выхода сеанса
crwdaq.logon/logout.
По результатам проверки посылается сообщение в Главную
Консоль.
По этому сообщению делается запись в журнал.
Исправлена ошибка в Database Browser/SQLook при редактировании на закладках Account и Location.
Редактирование строк подключения основано на шаблонах, в которых значения именованных параметров из шаблона заменяются на значения параметров из полей ввода. В процессе редактирования порой возникают ситуации, когда поля ввода оказываются пустыми. Например, пользователь при редактировании UserName может удалить старое значение имени пользователя, чтобы затем ввести новое. Ошибка заключалась в том, что при пустом значении в поле ввода параметр удалялся из шаблона, после чего ввод нового значения не имел результата, т.к. в шаблоне параметра просто нет. Ошибка (легко) исправилась проверкой поля ввода. При пустом значении поля замена не делается и параметр из шаблона не удаляется.
Сейчас редактирование вроде бы идет корректно.
В правила обработки системы контроля целостности Integrity введены вызовы @SysLog для записи событий в системный журнал.
Также добавлены логи ошибок XLib - графическая система X Window под Unix.
Было обнаружено, что многие Demo конфигурации сильно “спамят” в SysLog через процедуру Problem(…). Поэтому уровень SeverityOfProblemPolling понижен до INFO/Print, чтобы снизить уровень “спама” при стандартном уровне журнала.
Проблема (ещё) не решена окончательно, а (фактически) отложена. Дело в том, что для решения проблемы (возможно) потребуется править прикладные программы, чтобы делать вызовы Problem более обоснованно (не так часто как сейчас). Возможно, надо будет вводить дополнительные функции-обертки для предупреждений. Это еще надо обдумать.
А пока просто понижен уровень значимости Problem, чтобы не мусорила в журнале.
Артём Пергаев обратил внимание на некорректное поведение модальных окон (в версии под Linux). Например, модальное окно при сворачивании приложения не разворачивается обратно при его восстановлении. Получается, что окна пакета могут оказаться заблокированы невидимым (скрытым) модальным окном. Это создает у пользователя ложную тревогу, т.к. на первый взгляд кажется, что программа зависла. Хотя на самом деле программа просто ждет диалога и легко разблокируется нажатием Escape для закрытия скрытого модального окна.
Для решения этой проблемы в пакет добавлена служба
AwakeModal в меню “Окна/Будить модальные
окна”. Она включается ненулевым значением
AwakeModalWindowsMode в файле crwdaq.param.ini:
AwakeModalWindowsMode = 2 ; Режим опроса AwakeModal 0=OFF,1=Timer,2=Thread
AwakeModalWindowsFocus = 1 ; Флаг (0/1) "отдавать фокус ввода модальному окну"
AwakeModalWindowsPeriod = 5000 ; Период опроса службы AwakeModal в миллисекундах
Служба сканирует окна текущего процесса и ищет свёрнутые (спрятанные) модальные окна для данного процесса. Если точнее, ищутся окна, у которых одновременни присутствуют флаги состояния MODAL и HIDDEN. Если такие окна найдены, они разворачиваются и отображаются.
Параметр AwakeModalWindowsPeriod задает период опроса службы модальных окон в миллисекундах. По умолчанию служба делает проверку раз в 5 секунд (параметр AwakeModalWindowsPeriod=5000). Это достаточно редко, чтобы снизить нагрузку процессора, но вполне достаточно, чтобы пользователь не начал беспокоиться о зависании программы.
Параметр AwakeModalWindowsMode - задает
режим опроса службы модальных окон.
Для отключения службы модальных окон указывается AwakeModalWindowsMode=0.
Параметр AwakeModalWindowsFocus - флаг
(0/1) для активизации (передачи фокуса ввода)
модальному окну при выполнении службы модальных окон. Это нужно потому,
что под Unix возможна ситуация, когда открыто модальное
окно, но фокус ввода принадлежит другому (немодальному) окну того же
процесса. Если такая ситуация обнаруживается, то модальному окну
передается фокус ввода.
На данный момент принято решение включить службу модальных окон только под Unix, т.к. под Windows поведение модальных окон отличается и там эта служба вроде бы не нужна.
По грубой оценке производительности вызов службы модальных окон (под
Linux) занимает около
2+0.2*N [ms] при числе окон в сеансе
пакета N. Например, при 20 окнах это около 6 мс. Вызов
службы происходит раз в 5 сек, так что это (в среднем) 0.1% от одного
ядра CPU. В общем, это пренебрежимая мелочь.
На данный момент представляется, что служба модальных окон решает проблему скрытых модальных окон. Практика покажет, насколько это хорошее решение.
Немного изменено поведение функции SysLogNote, её формат упростился. Документация обновлена.
Введены константы sev_xxxx для уровней значимости. Численные значения точно заданы только для базовых уровней DEBUG,INFO,WARN,ERROR,FATAL,OFF. Для остальных уровней числовые значения (ещё) могут поменяться (пока всё не утрясётся), поэтому определены только имена.
Журнал SysLog внедрен в DAQ систему.
Внедрение сделано как на уровне компилятора, так и на уровне стандартной библиотеки:
Новая процедура Succeed работает аналогично Success, но имеет свой (более высокий) уровень значимости severity для журнала SysLog.
Процедуру Succeed пришлось ввести, чтобы выделить для занесения в журнал более значимые (успешные) события - такие как старт или завершение работы системы. Остальные (тоже успешные) события в процессе работы не так важны, поэтому для них вызывается Success. Слова succeed (успешно) и success (успех) являются синонимами, но succeed имеет оттенок “завершенной формы”, поэтому было выбрано для успешных событий высокого уровня значимости.
Процедуры - обёртки Trouble, Problem, Failure, Success, Succeed, ViewImp, ViewExp, Details имеют динамический уровень severity, зависящий от фазы выполнения Starting, Stopping, Polling. Дело в том, что ошибки при старте или остановке прикладной программы имеют более высокое значение, т.к. программа DaqPascal не работает, если при старте были ошибки. То есть ошибки при старте имеют фатальный характер. Поэтому надо разделять уровни журнала для этих фаз работы.
Внедрение журнала SysLog в стандартную библиотеку через процедуры - обёртки позволяет быстро задействовать функции журнала в уже имеющемся прикладном коде без необходимости его изменения.
Можно констатировать успешное выполнение первоначальных работ по журналу SysLog. Системный журнал SysLog в первом приближении реализован с записью в файл sys.log. По мере развития пакета будет добавляться регистрация тех или иных событий в журнале. Также со временем возможно занесение журнала в Базу Данных - если будет потребность.
На сегодняшний день основной функционал SysLog работает (с записью в файл). Возможно, ещё не все типы событий попадают в журнал - это станет ясно в процессе работы. Это не проблема - будем добавлять события в журнал по мере развития пакета.
Добавление записи журнала в Базу Данных не должна быть проблемой. Механизм сбора и обработки событий уже есть, так что надо только написать процедуру записи событий в Базу Данных - это несложно. Но сначала надо решить другие вопросы - в какую базу данных писать, как и где её создавать и (автоматически) конфигурировать. В общем, сначала потребуется работа по проектированию базы данных.
Продолжено внедрение журнала SysLog в код пакета.
Теперь (кроме прочего) в журнал SysLog заносятся:
Настройка уровней severity вынесена в файл crwdaq.sever.ini.
Это позволит облегчить настройку системы журналирования - не надо будет переписывать код, чтобы поменять уровни журналирования разного типа событий.
Для ускорения вызова обзора журнала SysLog сделана кнопка и меню Инструменты/Журнал Событий.
По кнопке открывается klogg с журналом sys.log.
Для повышения безопасности баз данных сделано шифрование паролей. Для этого пароль шифруется (например, в SQLook) и задается параметр PwdCryptMode, а также (в отдельных случаях) параметры PwdCryptKey, PwdCryptIv.
Например:
# Строка подключения БЕЗ ШИФРОВАНИЯ ПАРОЛЯ
Provider=IB;Database=sakila;HostName=localhost;UserName=SYSDBA;Password=masterkey;Charset=utf8;
# Строка подключения С ШИФРОВАНИЕМ ПАРОЛЯ
Provider=IB;Database=sakila;HostName=localhost;UserName=SYSDBA;Password=8KGjli65aKi2;Charset=utf8;PwdCryptMode=6;
Строку подключения с зашифрованным паролем можно получить в диалоге Database Browser или в программе SQLook.
Строку подключения в таком (шифрованном) виде можно сравнительно безопасно хранить в коде прикладной программы или в файле конфигурации, т.к. воспользоваться таким (зашифрованным) паролем вне программы DaqPascal будет затруднительно.
Кроме того, пароли могут передаваться (неявно) через переменные окружения.
Таким образом, проблема безопасного задания и хранения паролей для Баз Данных в первом приближении решена.
По примеру Tango добавлены переменные окружения DBAPI: MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT.
Если эти переменные заданы, то они будут задавать значения по умолчанию при подключении к MySQL для тех параметров, которые не указаны явно в строке подключения. Это позволит облегчить настройку и сопровождение систем, использующих базы данных.
Обновлена программа klogg для обзора журнальных файлов. Устанавливать/обновлять надо ручками, инсталлятор install-klogg.deb. Напомним, что у нас есть две программы обзора журналов - klogg (основная) и glogg (резервная).
Для программы klogg сделана утилита klogg-cpl для установки файлов настроек klogg, специально созданныых для работы в составе пакета crwdaq, с “правильными” регулярными выражениями для подсветки событий по типу (DEBUG/INFO/WARN/ERROR/FATAL).
unix klogg-cpl -i; # Install klogg settingsПрограмма klogg свободная и кроссплатформенная, есть под Unix и Windows. Она в целом решает проблему промотра журнальных файлов с подсветкой, поиском, фильтрацией, автоматическим обновлением и отслеживанием файла и т.д. Это хороший инструмент как для отладки, так и для штатной работы с журналами.
Сделан инсталлятор klogg для
Windows. Он автоматически устанавливает портативную
версию klogg в каталог
%SystemDrive%\opt\daqgroup\share\klogg.
Затем он копирует файл klogg.cmd и wintail.cmd в каталог
%UnixRoot%/usr/local/bin, так что
klogg и wintail становится доступным
через вызов unix klogg … или
unix wintail …. Всё это делается в
стартовом сценарии crwdaq.
Таким образом, теперь klogg заменяет wintail и является основным средством обзора журналов под системами Unix и Windows.
В обоих системах будет работать вызовunix klogg …илиunix wintail …
В функции ParamStr добавлены параметры: SysLogSeverityList, SysLogSeverityCode, SysLogSeverityName.
Например:
// Получить имя по коду
@paramstr syslogseverityname 15
INFO/NOTIFY
// Получить код по имени
@paramstr syslogseveritycode info/notify
15В DaqPascal добавлены функции: SysLogNotable, SysLogNote.
Это базовые функции для записи событий в системный журнал.
Вероятно,они будут использоваться не напрямую, а в обёртке функций стандартной библиотеки, таких как Success, Trouble и других.
Вызовы SysLog внедрены в:
Теперь надо аккуратно внедрить SysLog в стандартную
библиотеку StdLibrary.
Этим и займемся в ближайшее время.
В движках SQLDB, ZEOS библиотеки DbApi сделана поддержка некоторых переменных окружения, чтобы получить возможность неявно задавать некоторые параметры подключения, т.е. не указывать их явно в строке подключения, а брать из окружения.
Поддерживаются такие переменные:
# Для Interbase/Firebird
ISC_USER=… # Имя пользователя
ISC_PASSWORD=… # Пароль пользователя
# Для PostgreSQL
PGUSER=… # Имя пользователя
PGPASSWORD=… # Пароль пользователя
PGHOST=… # Имя сервера
PGPORT=… # Номер порта
# Для всех провайдеров
DBAPI_USER=… # Имя пользователя
DBAPI_PASSWORD=… # Пароль пользователя
DBAPI_HOST=… # Имя сервера
DBAPI_PORT=… # Номер портаПеременные окружения запрашиваются только в случае, если соответствующий параметр не задан явно в строке подключения. Это позволяет задавать параметры “по умолчанию”, которые задаются в окружении и не требуют явного указания.
Переменные окружения DBAPI_XXX имеют более низкий приоритет, т.е. если вместе с переменной DBAPI_USER одновременно задана переменная ISC_USER, то для Firebird будет задействована именно она.
Переменные окружения DbApi призваны облегчить прикладное программирование. Если задать переменные окружения в одной (основной) программе при старте, то прикладные программы смогут подключаться к базе данных без явного указания пользователя и пароля.
Создан модуль _crw_syslog.pas для реализации системного журнала SysLog. Читайте мануал.
В окне Главная Консоль добавлена команда @syslog для работы с Системным Журналом.
# Задать уровень журналирования
@syslog -t info/notify
# Сделать запись в Системный Журнал
@syslog info/notify demo - Тестовая запись.
# В журнале появится запись вида
# 2025.08.21-14:43:43.264 => INFO/NOTIFY: crwdaq_1/demo - Тестовая запись.Фиксируется время, значимость (severity), источник сообщения
(sender) и затем после обязательного маркера
' - ' идет само сообщение.
При наличии “вредных” символов (типа перевода строки) сообщение
кодируется в pct-encode.
Это нужно для корректной записи сообщений в журнальный файл.
Можно констатировать готовность (в первом приближении) прикладного интерфейса к Базам Данных.
- В DbApi добавлено два движка - SQLBD и ZEOS, оба работают стабильно.
- Дополнена библиотека DbLibrary для облегчения прикладной разработки.
- Сделана (первичная) поддержка BLOB полей баз данных.
- Сделана утилита SQLook для обзора баз данных.
- Доработан сервер &FdbSrv для записи данных.
- Собраны утилиты и драйверы для работы с БД.
- Есть демо конфиги и какая-то документация.
Интерфейс к БД (в первом приближении) готов к использованию в прикладных задачах.
Над чем еще стоит поработать по теме поддержки БД:
Из других задач ToDo по завершению перевода пакета:
После этого пакет crwdaq достигнет уровня развития
старой версии crw32.
Далее уже пойдет чистое развитие новой версии, без оглядки на
старую.
В плане развития - список ToDo:
А дальше посмотрим.
В DaqPascal добавились функции: ReadFileToBuffer, WriteBufferToFile, GetFileProperties.
Как легко догадаться, это функции чтения/записи в файл и получание свойств файла. Отличие от обычных файловых операций состоит в том, что это операции атомарные, т.е. данные читаются все сразу, одной операцией. Открытие файла, чтение/запись и закрытие файла спрятаны внутри функций. Это удобно, когда надо прочитать/записать файл целиком, а всю обработку данных делать в буфере памяти.
Функция GetFileProperties весьма полезна, т.к. позволяет одним вызовом получить сразу список свойств файла в виде куки-списка (Ключ=Значение+EOL).
Читайте справку. Пример:
// Чтение списка компьютеров hosts
buff:=ReadFileToBuffer('/etc/hosts/',0,0);
// Запись буфера в файл
n:=WriteBufferToFile('/tmp/test.txt',buff,0);
if (n>0) then writeln('Записано ',n,' байт');
// Чтение свойств файла
fname:='/tmp/test.txt';
buff:=GetFileProperties(fname,'Size,Permissions,Owners');
writeln('Размер файла ',CookieScan(buff,'Size',0));
writeln('Права файла ',CookieScan(buff,'Permissions',0));
writeln('Владельцы файла ',CookieScan(buff,'Owners',0));
цкшеудт('Все свойства файла ',GetFileProperties(fname,''));Имейте в виду, что некоторые свойства (например, Permission,Owners)
доступны только в Unix.
Под Windows они отсутствуют. Другие свойства (например,
Attr) зависят от системы.
Это не проблема функции, просто файловые системы очень разные.
Для работы с блобами (двоичных данных из баз данных) добавлена новая подфункция ParamStr DetectBlobImageType. Она пытается определить, является ли блоб изображением одного из известных типов и возвращает имя этого типа (которое берется по общепринятым расширениям файлов).
Пример:
procedure TestDetectBlob;
var blob,what:String;
begin
blob:=''; what:='';
writeln('Test DetectBlobImageType');
blob:=ReadFileToBuffer('/opt/crwkit/add/png/dim.png',0,0);
what:=ParamStr('DetectBlobImageType b64 '+base64_encode(blob));
if IsSameText(what,'png')
then Success('Detected PNG blob.')
else Problem('Could not detect blob.');
blob:=''; what:='';
end;В базах данных блобы хранятся без имен файлов, поэтому определить тип блоба можно только по содержимому блоба - по сигнатуре и эмпирическим признакам. Это определение носит вероятностный характер, т.к. сигнатуры могут случайно совпасть. Однако вероятность ошибки невелика и функция будет полезной при анализе баз данных.
В конфигурацию demo_testbench добавлен
@Test 22.
Он проверяет работу новых функций работы с файлами, а также делает замеры производительности некоторых интересующих функций.
Для удобства прикладного программирования в DbLibrary добавлены функции:
Это чисто вспомогательные функции для облегчения анализа данныых при работа с базами данных.
В стандартную библиотеку добавлены строковые функции общего применения: IsNonEmptyStr, TailStr, RightStr, LeftStr, StrAheadOf, StrAfterOf, ContainsStr, StartsStr, EndsStr, ContainsText, StartsText, EndsText.
Эти функции есть в библиотеке FPC и crwlib, они показали свою полезность. Поэтому их хотелось бы иметь под рукой и в DaqPascal. Практика показывает, что программирование процентов на 50 состоит из анализа строк. Набор этих функций позволяет анализировать строки в удобном виде:
uri:='http://simply/postbox/manual.pdf';
if StartsStr('http://',uri) then writeln('Наверное, это Web адрес.');
if EndsStr('.pdf',uri) then writeln('Наверное, это PDF - документ.');
writeln('Протокол связи ',StrAheadOf(uri,':'),', ожидается "http".');В тестовой базе данных sakila в таблице staff есть поле picture типа BLOB. Однако это поле почему-то оставили пустым. Поскольку для проверки работы полей BLOB была нужна тестовая база данных, то с помощью программы dbeaver-ce в базу добавлены изображения .png в полях BLOB. Это сделано для файлов SQLite и Firebird - sakila.db, sakila.fdb и employee.fdb. Для других тестовых баз данных блобы при необходимости добавляются “ручками”.
Когда появилась возможность работы с блобами, были проведены тесты, которые показали, что функция db_FieldsAsString корректно считывает блобы в виде строки с бинарными данными. Это радует - не надо вводить новых функций DbApi для блобов.
Чтение блобов проверено для SQLDB,ZEOS и
SQLite,Firebird.
Всё читается нормально.
Некоторая поддержка добавлена в SQLook и Database Browser.
Добавилась закладка BLOB View, на которой задается режим отображения BLOB полей:
BLOB_MARKER - отобразать вместо блоба маркер BLOB/bin
BLOB_DETECT - определять формат блоба BLOB/png и т.д.
BLOB_AS_IS - отображает строку блоба "как есть"
B64_ENCODE - отображать блоб в кодировке base64-encode
HEX_ENCODE - отображать блоб в кодировке hex-encode
PCT_ENCODE - отображать блоб в кодировке percent-encode
Необходимость кодирования связана с тем, что StringGrid может некорректно отображать бинарные строки, т.к. он ожидает строки UTF8. Кодирование гарантирует читабельность. Кодированные данные можно скопировать и декодировать, если их надо извлечь в исходном виде.
В случае, если в блобе хранится изображение и выбран режим отображения блоба B64/HEX/PCT, то доступна функция просмотра блоба как изображения, при этом блоб сохраняется во временный файл и отображается внешней программой просмотра изображений - xdg-open под Linux или unix imagine под Windows.
Также возможно отображение блоба в виде шестнадцатеричного дампа (dump). Для этого надо поставить галочку в закладке BLOB View, в чекбоксе View as Dump.
Поскольку для создания дампа используется программа xxd, которая есть в репозитории, но по умолчанию не стоит, то эта программа внесена в список зависимостей crwdep и в зависимости инсталлятора. Это под Unix. А под Windows программа xxd входит в UnixUtils.
Николай Гурин подготовил две игровые DAQ-конфигурации.
demo_game_pacman - демо
конфигурация “Игра Pacman”.
Это симпатичная реализация классической игры 1980 года
(прямо ностальгия просыпается).
Является прекрасной демонстрацией графических возможностей пакета.
См. справку
demo_game_stf - демо
конфигурация “Игровой Синхротрон”.
Это игровая модель системы управления воображаемым (игровым)
синхротроном.
Является прекрасной демонстрацией возможностей графических
мнемосхем.
Также иллюстрирует интересные подходы к построению интерфсейса
пользователя.
См. справку
Игры - не такая уж бесполезная вещь, как принято думать.
Недаром именно с игр началось широкое развитие компьютерной
индустрии.
Игры (и особенно их разработка) являются прекрасным способом
демонстрации
возможностей модельных систем и наработки разных подходов к
программированию,
построению алгоритмов управления, интерфейсов пользователя и т.д.
Это хороший полигон для моделирования фрагментов реальных систем
управления,
на которых можно отрабатывать те или иные алгоритмы и интерфейсы.
В этом несомненная польза игровых DAQ-конфигураций.
В общем, появление нового жанра (игровые DAQ-конфигурации) можно только приветствовать.
Хорошая работа.
Расширен набор списков ListOf. Добывлены списки DAQ-системы (пока только самые общие): daq_tags, daq_curves, daq_devices, daq_windows.
// Список тегов DAQ системы
s:=ParamStr('ListOf daq_tags');
// Тег по имени
s:=ParamStr('ListOf daq_tags where name=DEMO.TAG');
// Список кривых DAQ системы
s:=ParamStr('ListOf daq_curves');
// Кривая по имени
s:=ParamStr('ListOf daq_curves where name=DEMO.CURVE');
// Список устройств DAQ системы
s:=ParamStr('ListOf daq_devices');
// Устройства по имени, семейству и модели
s:=ParamStr('ListOf daq_devices where name=&DEMO.DEVICE');
s:=ParamStr('ListOf daq_devices where family=software, model=program');
// Список окон DAQ системы
s:=ParamStr('ListOf daq_windows');
// Окна по имени(заголовку) и типу
s:=ParamStr('ListOf daq_windows where name=MAIN.CTRL');
s:=ParamStr('ListOf daq_windows where type=TAB_WINDOW');
s:=ParamStr('ListOf daq_windows where type=CURVE_WINDOW');
s:=ParamStr('ListOf daq_windows where type=SPECTR_WINDOW');
s:=ParamStr('ListOf daq_windows where type=CIRCUIT_WINDOW');Формат вывода для этих списков аналогичен тому, который
используется
в конфигурационных файлах при определении соответствующих
объектов.
Например:
@ParamStr ListOf daq_tags where name=DEMO.TAG
DEMO.TAG=Real 3.14
@ParamStr ListOf daq_curves where name=DEMO.CURVE
DEMO.CURVE=Curve 0 1024 BLACK 1 1
@ParamStr ListOf daq_devices where name=&DEMO.DEVICE
&DEMO.DEVICE=Device SOFTWARE PROGRAM
@ParamStr ListOf daq_windows where name=MAIN.CTRL
MAIN.CTRL=CIRCUIT_WINDOWСо временем список списков будет еще более расширен, просто трудно включить сразу всё. Это будет делаться постепенно.
Еще одна небольшая доработка сервера &FdbSrv.
При переводе под новую версию пакета было отключено сохранение в режиме FastTransfer. Это была временная мера, связанная с экономией времени на отладку. Напомним, что запись данных может происходить по командам SQL, когда данные передаются в текстовом виде, или через работу с записями recordset, когда данные передаются в двоичном виде. Режим FastTransfer использует передачу данных в двоичном виде - что, естественно, быстрее.
Одной из причин отказа от режима FastTransfer было то, что в (единственном на тот момент) движке ADO время DateTime при работе с записями округляется до секунды, что во многих случаях неприемлемо.
Сейчас режим FastTransfer восстановлен и протестирован - вроде бы всё в порядке.
Проблемы с округлением времени с использованием FastTransfer в двоичном режиме с движками SQLDB и ZEOS не обнаружено.
Сервер &FdbSrv прошел первичное тестирование и выглядит готовым к использованию.
Добавление к теме арресов URI - добавлены лексемы lex_PctChar, lex_PctCode, lex_PctData, lex_PctNeed.
Эти лексемы касаются разных аспектов pct-encode и адресов URI. Читайте мануал.
Просто на заметку.
Для запуска .desktop файлов есть штатная утилита xdg-open. Она у нас используется уже давно - например, в crwkit.
Оказывается, есть еще одна штатная утилита
gtk-launch, она устанавливается по
умолчанию и находится (кажется) в пакете
libgtk2.0-bin.
Польза этой утилиты в том, что она умеет запускать
.desktop файлы стандартных приложений по
короткому имени.
Файлы стандартных приложений лежат обычно в /usr/share/applications.
# запуск с коротким именем
gtk-launch fb-cpl
# запуск с коротким именем и расширением
gtk-launch fb-cpl.desktop
# запуск с полным именем и расширением
xdg-open /usr/share/applications/fb-cpl.desktopОбратите внимание - утилита xdg-open работает только с полным именем файла, а утилита gtk-launch - только с коротким именем, при этом файл ищется в каталоге приложений /usr/share/applications и, возможно, других известных системе каталогах.
Эти “запускалки” надо иметь в виду.
Расширен набор списков ListOf. Добывлены списки users, groups, hosts, environs, ftypes.
// Список пользователей
s:=ParamStr('ListOf users');
// Проверка наличия пользователя
if (ParamStr('ListOf users where name=main')<>'')
then writeln('User "main" is exists.');
// Список групп в которые входит текущий пользователь
s:=ParamStr('ListOf groups');
// Проверка членства пользователя в группе
if (ParamStr('ListOf groups where name=firebird')<>'')
then writeln('User is member of group "firebird"".');
// Список компьютеров
s:=ParamStr('ListOf hosts');
// Проверка наличия компьютера
if (ParamStr('ListOf hosts where name=simply')<>'')
then writeln('Host "simply" is exists.');
// Список переменных окружения
s:=ParamStr('ListOf environs');
// Чтение переменной окружения PATH
s:=ParamStr('ListOf environs where name=PATH');
// Список типов файлов ftype/MIME
s:=ParamStr('ListOf ftypes');
// Чтение обработчика файлов text/html
s:=ParamStr('ListOf ftypes where name=text/html');Примечания:
Список users включает локальных пользователей. Пользователи домена сюда не входят.
Список hosts берется из /etc/hosts. В него не входят компьютеры, зарегистрированные через службу DNS.
Список ftypes под Linux возвращает список обработчиков, разделенных символом ;. Это короткие имена .desktop файлов стандартных приложений, которые можно вызвать через gtk-launch. Первый элемент списка обработчиков - используемый по умолчанию.
Доработан сервер &FdbSrv.
Улучшен анализ ошибок. До этого не все ошибки “ловились”.
При возникновении некоторых исключений это не фиксировалось.
Теперь это исправлено.
Решена проблема с правами доступа создаваемых
.fdb файлов.
Напомним, проблема была с правами доступа создаваемых файлов
баз данных .fdb, которые имели права
rw-rw----, из-за чего
другие пользователи не имели к ним доступа. В частности,
не имел доступа сервер Firebird, работающий
под пользователем firebird.
Сейчас алгоритм работает так.
rw-rw-rw-,rw-rw----, как
предусмотрено сервером.Таким образом, доступ к файлам должен быть как без установки
сервера
(в этом случае клиентская библиотека работает с локальными файлами
напрямую),
так и с установленным сервером (в этом случае сервер сам управляет
правами файлов).
Исправлена ошибка в диалоге Database Browser, возникающая при чтении списка таблиц. Недавно был введен новый (более корректный) способ чтения списка таблиц, но не было замечено, что он дает сбои при наличии пробелов в именах таблиц. Сам по себе список таблиц получается верный, но ошибка возникала при извлечении элементов списка (был взят неверный набор символов-разделителей и не учитывались строки в кавычках). Это проявлялось в том, что имена таблиц с пробелами извлекались как несколько отдельных слов (что неверно). Теперь это исправлено.
В набор crwlib добавлен модуль _crw_prmstrlst.pas.
Модуль содержит единственную (но сложно устроенную внутри) функцию
ParamStrListOf(arg), которая служит для реализации
“списка ВСЕГО” (т.е. списка разных системных
параметров), а главное, для реализации
paramstr('listof …') в
DaqPascal.
В функции paramstr реализована опция
(подфункция) listof или, как
синоним, getlistof.
Эта новая опция превращает paramstr в подобие базы
данных с SQL-подобными запросами в виде:
// Общий формат вызова
data:=ParamStr('ListOf TABLE'); // Чтение всей таблицы TABLE
data:=ParamStr('ListOf TABLE where key1=value1, key2=value2'); // Выборка по значениям ключей
// Например:
s:=ParamStr('ListOf tables'); // Получить список всех доступных таблиц
s:=ExtractWord(1,ParamStr('ListOf pids where name=firebird')); // Получить PID процесса с именем fireberd
s:=ParamStr('ListOf colors where name=Lime,format=web'); // Код цвета Lime в WEB-формате #00FF00Таблица или выборка возвращается в виде строки текста (с разделителем
EOL).
Формат полученного текста определяется таблицей, но обычно это список
слов, разделенных запятой и/или пробелами.
При выборке значений формат может отличаться от формата всей таблицы
(это зависит от таблицы и ключей).
Проверить работу listof можно в любой консоли
Daq-устройства командой
@paramstr listof ….
Например:
///////////////////////////////////////////////////////////////////
// Выполнено в консоли &TESTBENCH демо-конфигурации demo_testbench:
///////////////////////////////////////////////////////////////////
// Список всех доступных таблиц
@paramstr listof tables
specfolders,colors,comports,tables,threads,services,keys,pids,processes,tasks,windows,netifs,modules
// Список ключей для всех доступных таблиц
@paramstr listof keys
pids keys: pid,ppid,name
processes keys: pid,ppid,name
modules keys: pid
windows keys: pid,class,title,mode
threads keys: name
tasks keys: tid,pid
colors keys: name,code,format
netifs keys: mode
specfolders keys: name
services keys: name,port,protocol
comports keys: name,path
keys keys: name
tables keys: name
// Процесс по имени
@paramstr listof pids where name=dns
793241, 1, 120, dns
// COM-порт по имени
@paramstr listof comports where name=com1
COM1 /dev/ttyUSB0 pl2303
// Имя цвета по коду
@paramstr listof colors where code=$00ff00,format=str
LimeСмотрите также описание.
В настоящее время реализовано около 10 системных
таблиц.
В будущем планируется существенно расширить набор доступных
таблиц,
чтобы сделать paramstr(listof) универсальным средством
доступа к “списку ВСЕГО”.
При работе сервера &FdbSrv была обнаружена
проблема с правами создаваемых файлов
*.fdb.
Эти файлы (под Unix) создаются с правами
rw-rw----, то есть как недоступны для
чтения другим пользователям. Поэтому при обращении через
localhost возникает ошибка доступа, т.к. сервер
firebird работает под пользователем
firebird. Эта ошибка не проявляется, если работать без
установки сервера (на чисто клиентских библиотеках). Однако работа с
сервером будет для нас основной, поэтому проблему надо решать. Решение
этой проблемы входит в ближайшие планы.
Введенные в предыдущие дни функции анализа URI позволили реализовать
строки подключения в стиле DB
URI.
Это строки подключения в стиле Web адресов. Эта
возможность доступна только для движков SQLDB,
ZEOS.
// Общий вид строки подключения в стиле DB URI:
uri:='provider://user:pass@host:port/dbname?key1=value1&key2=value2&...';
// Для движка SQLDB, Firebird и провайдера IB:
uri:='IB://SYSDBA:masterkey@localhost/employee.fdb?Charset=utf8&PageSize=4096#Example';
con:=db_connection(db_engine_sqldb,uri);
// Для движка ZEOS, Firebird и провайдера firebird:
uri:='firebird://SYSDBA:masterkey@localhost/employee.fdb?Charset=utf8&PageSize=4096#Example';
con:=db_connection(db_engine_zeos,uri);Строки подключения в стиле DB URI могут оказаться удобными, т.к. они получаются похожими на адреса Web, к которым многие привыкли.
Формат DB URI соответствует (с точностью до названий
компонентов) стандарту RFC-3986.
По этому стандарту URI имеет форму
scheme://authority/path?query#fragment,
примерно так:

Следует заметить, что строки подключения в стиле DB URI являются временной и вспомогательной формой. При вызове db_connection строка подключения автоматически преобразуется в (основную) форму куки (т.е. в форму списка имя=значение, разделенных [;] точкой с запятой) и дальнейшая обработка идет так же, как с обычной строкой подключения.
В набор crwlib добавлен модуль _crw_uri.pas. Модуль, как легко догадаться, предназначен для анализа адресов URI, формат которых описан в RFC-3986. Все адреса ресурсов в сети Internet соответствуют (должны) этому стандарту.
В модуле также реализована процентная кодировка pct-encode.
В модуле также есть функции поддержки и поиска сетевых служб (services), т.е. известных системе сетевых портов (для протоколов tcp, udp) и соответствующих имен служб. Например, службе ssh соответствует порт 22/tcp. В системах Unix сетевые службы обычно описываются в файле /etc/services. В Windows сетевые службы обычно описываются в файле /windows/system32/drivers/etc/services.
В функцию IsLexeme добавлены лексемы
Составные имена часто применяются в программировании, а формат URI используется для адресации ресурсов в сети Internet, в частности, в запросах HTTP. Поэтому удобно уметь их идентифицировать.
В компилятор DaqPascal добавлены функции pct_encode, pct_decode, pct_encoder_ctrl и их синонимы percent_encode, percent_decode, percent_encoder_ctrl.
Процентная кодировка (pct-encode или percent-encode) проще и понятнее, чем кодировка URL, которая (теперь) считается устаревшей. В будущем следует (по возможности) отдавать предпочтение pct-encode вместо url-encode.
В функции paramstr добавились параметры/подфункции FetchUriScheme, FetchUriAuthority, FetchUriPath, FetchUriQuery, FetchUriFragment, FindServicePort, ServicePortName, ServicePortInfo, ServicePortList.
Это функции разбора URI адресов и поиска сетевых служб.
Команда @ParamStr в консоли устройств DAQ позволяет вызывать эти функции интерактивно.
# Разбор адресов URI
@paramstr FetchUriScheme http://main@simply/www.crw-daq.ru?query#example
> http
@paramstr FetchUriAuthority http://main@simply/www.crw-daq.ru?query#example
> main@simply
@paramstr FetchUriPath http://main@simply/www.crw-daq.ru?query#example
> /www.crw-daq.ru
@paramstr FetchUriQuery http://main@simply/www.crw-daq.ru?query#example
> query
@paramstr FetchUriFragment http://main@simply/www.crw-daq.ru?query#example
> example
# Изучение сетевых служб
@paramstr FindServicePort ssh
> 22
@paramstr ServicePortName 22
> ssh
@paramstr ServicePortInfo 22
> ssh # SSH Remote Login Protocol
@paramstr ServicePortList
> (список сетевых служб)
@paramstr EtcServicesFile
> /etc/servicesОбратите внимание, после выделения компонентов URI может потребоваться pct_decode, если в компоненте есть символ процента (то есть закодированные символы).
Новые функции служат для облегчения работы с URI сетевыми адресами по стандарту RFC-3986, а также с сетевыми службами и протоколами.
Обновлен demo_testbench. В @test 4 и @test 6 добавлены проверки новых функций/подфункций.
Сделаны мелкие правки в SQLook, конфигурационных .ini файлах.
В репозиторий возвращен пакет DBeaver, поскольку он вроде бы полезен.
К нему прилагаются драйверы /opt/daqgroup/share/dbdrivers/jdbc-all-jar.
Их надо инсталлировать в пакете dbeaver.
Также добавлена утилита dbvis,
аналогичная dbeaver.
Она тоже использует драйверы jdbc.
Как показало тестирование и изучение кода SQLDB и ZEOS, гипотеза о том, что проблемы при чтении таблиц возникают из-за блобов (BLOB/TEXT), была ошибочной.
На самом деле с блобами всё нормально. Например, блоб BLOB sybtype 1 - он же BLOB/TEXT - проецируется в SQLDB и ZEOS на тип ftMemo и возвращается как длинная строка.
Проблемы всё же есть, но они возникают с типом SQL_ARRAY, который проецируется в SQLDB и ZEOS на тип ftArray. В настоящее время эти движки (оба) не поддерживают тип полей данных ftArray и генерируют исключение, если обнаруживают его при чтении данных из SQL запроса.
Хорошая новость в том, что эту проблему можно (частично) обойти.
Для этого надо в SQL запросе чтения таблицы,
содержащей поля типа ftArray указывать не все поля
(*), а список конкретных интересующих
полей (не типа ftArray) для чтения, исключив поля типа
ftArray из запроса. В этом случае поля типа
ftArray просто не читаются и исключения не
возникает.
Например, при чтении таблицы JOB из тестовой базы
данных employee сервера Firebird
запрос select * from JOB; даст ошибку
(исключение) и данные не прочитаются, так как в поле с именем
LANGUAGE_REQ содержится массив
ftArray. Однако запрос, например,
select JOB_SALARY,JOB_COUNTRY from JOB;
будет выполнен успешно.
Исключение при чтении полей типа ftArray не является “багом” (явной ошибкой) - это скорее недоработка. Из анализа кода SQLDB и ZEOS следует, что поддержка типа ftArray просто не реализована. Видимо, у разработчиков до сих пор руки (и ноги) не дошли до этого. Так что пока поля типа ftArray для этих движков недоступны.
Справедливости ради надо сказать, что с поддержкой этого типа вообще всё непросто. Многие из протестированных браузеров баз данных имеют те или проблемы с типом SQL_ARRAY - поля этого типа или не читаются, или читаются с ошибками.
Для тестирования и проверки программ работы с базами данных нужны тестовые примеры БД.
В нашем случае примеры собраны в папках:
В движках SQLDB, ZEOS для чтения списка таблиц появился новый метод (которого нет в движке ADO).
// Чтение списка таблиц (открытого) соединения con
if db_active(con) then begin
prop:=db_ctrl(con,'Properties=Connection.TableNames');
tabs:=CookieScan(prop,'Connection.TableNames',Ord(';'));
if (tabs<>'') then writeln('Table Names: ',tabs);
end;Этот пример вызовом db_ctrl читает свойство
(Properties) по имени Connection.TableNames -
список таблиц текущей открытой БД. Вызов возвращает
строку вида
Connection.TableNames=table1,table2,…; со
списком имен таблиц, разделенных запятыми. Список извлекается вызовом
CookieScan и далее используется по назначению.
В будущем этот метод чтения списка имен таблиц будет, видимо, основным.
А сейчас утилита SQLook обновлена с использованием этого метода чтения имен таблиц.
В сборку crwkit добавлена утилита sqlook.
Вызов:
unix sqlookЭто диалог “Databаse Browser”, выделенный из пакета crwdaq для автономного использования.
Также sqlook добавлен в
unix fb-cpl --run-sqlook и в меню
“Старт/Сеть/Панель управления Firebird”.
В функцию IsLexeme добавлены опции
Эти функции нужны для проверки корректности сетевых адрессов компьтеров и сетевых карт.
Такие адреса могут использоваться для идентификации серверов баз данных.
В demo_testbench сделано обновление @Test 4 для проверки новых опцией функции IsLexeme. Вроде с функцией всё хорошо.
В функцию IsLexeme добавлены опции
Эти функции нужны для проверки корректности локальных и сетевых имён пользователей и компьтеров.
В Строке Подключения db_connection формат
Database теперь может иметь вид
USERNAME:PASSWORD@HOSTNAME:DATABASE,
например:
con:=db_connection(db_engine_sqldb,'Provider=IB;Database=sysdba:masterkey@localhost:employee;');
// IB - провайдер Firebird
// sysdba - имя пользователя
// masterkey - пароль пользователя
// localhist - имя сервера
// employee - имя базы данныхТакая подстановка работает только в движках SQLDB, ZEOS.
При этом, если в строке подключения явно указывается имя/пароль пользователя или сервер, то этим (явным) значениям отдается предпочтение.
Анализ строки подключения делается с помощью новых опций IsLexeme, перечисленных выше.
В репозиторий daqgroupkit добавлено два пакета:
Обе программы добавлены в репозиторий, но устанавливаются
вручную.
Это потому что они не всегда нужны (это отладочный инструмент для
разработчиков).
Обе программы добавлены в утилиту
unix fb-cpl и доступны в меню.
При вызове unix fb-cpl -d она, помимо
установки меню, вносит две поправки в файлы
Firebird.
WireCrypt = EnabledWireCrypt = Required
приводит к тому, что некоторые клиенты,С новыми библиотеками, движками DbApi и инструментальными утилитами вопрос инструментария для поддержки Баз Данных под Windows и Linux (пока) закрыт.
Дальше уже идет прикладное программирование.
Для администрирования Баз Данных была найдена хорошая программа - FlameRobin (что значит пламенный дрозд). Домашний сайт www.flamerobin.org/. Это мощная программа для администрирования и обзора Баз Данных сервера Firebird. Она маленькая, многофункциональная и кроссплатформенная. Её просто необходимо иметь в наборе инструментов.
Поэтому в репозиторий daqgroup добавлен пакет
daqgroup-flamerobin.
Она устанавливается через вызов
install-daqgroup-flamerobin.run и входит в набор
install-daqgroup-all.run.
В стандартном репозитории Astra и даже Debian этой утилиты нет. Поэтому утилита собрана из исходников, которые есть в папке репозитория database/flamerobin.
Утилита flamerobin практически закрывает вопросы создания, удаления, копирования, клонирования, обслуживания Баз Данных сервера Firebird. Поскольку у нас работает сервер сохранения данных FdbSrv в формате Firebird, это актуальный вопрос.
Также программа FlameRobin добавлена в системное меню и в Панель Управления Firebird.
В утилиту fb-cpl добавлено меню Панель Управлени Firebird (на базе zenity), а также команда для установки этого меню в системном меню Пуск/Сеть:
unix fb-cpl --menu # Вызвать меню - Панель Управлени Firebird
unix fb-cpl --desktop-menu # Добавить меню в системном меню Пуск/СетьТакже это меню устанавливается при установке crwkit.
Это должно облегчить установку и облуживание сервера Firebird.
В сборку crwkit добавлена утилита
fb-cpl. Она служит для управления сервером
Firebird. Например:
# Install Firebird Server
$ unix fb-cpl -i;
Already Installed: firebird3.0-common
Already Installed: firebird3.0-server
Already Installed: firebird3.0-utils
Already Installed: firebird3.0-doc
Already Installed: firebird-dev
Nothing to install.
# Add current user (alex) to group (firebird).
$ unix fb-cpl -u;
User alex is now in group firebird.
You need restart session to apply this.
# Check client libraries.
$ unix fb-cpl -c;
/lib/x86_64-linux-gnu/libfbclient.so
/lib/x86_64-linux-gnu/libfbclient.so.2
/lib/x86_64-linux-gnu/libfbclient.so.3.0.11
# list running firebird server(s).
$ unix fb-cpl -l;
2536 /usr/sbin/firebird
# Which firebird? Print firebird location.
$ unix fb-cpl -w;
/usr/sbin/firebird
# Check status of firebird service.
$ unix fb-cpl -s;
● firebird3.0.service - Firebird Database Server ( SuperServer )
Loaded: loaded (/lib/systemd/system/firebird3.0.service; enabled; preset: enabled)
Active: active (running) since Tue 2025-07-22 19:32:56 MSK; 4h 8min ago
Docs: https://firebirdsql.org/en/firebird-rdbms/
Process: 2514 ExecStart=/usr/sbin/fbguard -daemon -forever (code=exited, status=0/SUCCESS)
Main PID: 2534 (fbguard)
Tasks: 4 (limit: 18992)
Memory: 11.4M
CPU: 85ms
CGroup: /system.slice/firebird3.0.service
├─2534 /usr/sbin/fbguard -daemon -forever
└─2536 /usr/sbin/firebird
# Restart firebird service.
$ unix fb-cpl -r;
Restarting firebird3.0 (via systemctl): firebird3.0.service.
# Show help.
$ unix fb-cpl -h
fb-cpl version 1.0
Copyright (c) 2001-2025 Alexey Kuryakin daqgroup@mail.ru
Firebird/Interbase server/client control panel tool.
Usage: fb-cpl [-options]
Options:
-h,--help - show help
--version - show version
-l,--list - list firebird server pid cmd
-w,--which - print firebird binary pathname
-s,--status - see status of firebird service
-r,--restart - restart firebird service
-b,--start - begin (start) firebird service
-q,--stop - quite (stop) firebird service
-c,--client - print client library locations
-u,--user - add current user to group firebird
-i,--install - install firebird required packages
-m,--menu - show Menu - Firebird Control Panel
-d,--desktop-menu - setup Desktop Menu in Start Button
Examples:
fb-cpl --help # show help
fb-cpl --version # show version
fb-cpl -l # list firebird pid cmd
fb-cpl -s # check firebird status
fb-cpl -i # install firebird packagesТут нужно сделать несколько пояснений.
unix fb-cpl -i;SYSDBA - администратора
СУБД,masterkeyunix fb-cpl --reconfig;unix fb-cpl -u; -
после этогоunix fb-cpl --help;Замечена интересная особенность Firebird под Linux.
Если Firebird сервер не установлен, но установлен клиент (а он установлен по умолчанию), то DbApi может читать локальные файлы .fdb, но не может читать их при указании сервера, например, localhost. Для работы в этом режиме сервер вообще не должен указываться в строке подключения. Также при работа в этом режиме клиентская библиотека устанавливает эксклюзивный доступ к файлам .fdb - пока один поток пишет данные, другие не могут подключиться.
Если Firebird сервер установлен, но пользователь не включен в группу firebird, то доступа к базе данных нет - даже для локальных файлов без указания сервера.
Если Firebird сервер установлен и пользователь включен в группу firebird, то есть доступ к базе данных для локальных файлов - как с указанием, так и без указания сервера. Кроме того, доступ теперь становится общим, с возможностью параллельного чтения и записи.
Учитывая, что сервер Firebird - “легкий”, весит и
потребляет мало ресурсов, есть смысл на всех машинах ставить
Firebird сервер вызовом
unix fb-cpl -i; и включать пользователя в
группу firebird вызовом
unix fb-cpl -u; - с последующей
перезагрузкой сеанса.
Однако это не делается автоматически при инсталляции пакета, т.к. там
есть ручные операции. Во-первых, это ввод пароля
SYSDBA в диалоге. Во-вторых, требуется
перезагрузка сеанса.
Поэтому эти операции (пока) будут делаться вручную.
В функцию IsLexeme добавлены опции
Эти функции нужны для проверки корректности локальных и сетевых имён компьтеров.
Сетевые имена регламентируются стандартами RFC-921, RFC-952, RFC-1123.
В диалоге Database Browser добавлена маленькая кнопочка Save на закладке SQL expression. По этой кнопке можно сохранять таблицы в файле в формате CSV,TXT,XML. Сохраняется таблица, прочитанная согласно тексту SQL запроса в окне SQL expression.
Немного дополнена документация DbApi. Проводилось тестирование и мелкие доработки кода.
Можно резюмировать, что интерфейс DbApi к базам данных с двумя движками SQLDB и ZEOS - готов к использованию в первом приближении.
Он работает под Windows и Linux. Там еще есть над чем поработать (много мелких деталей), но базовый функционал готов.
В ближайшее время будем копать тему ODBC.
Поскольку новая версия пакета включает компоненты библиотеки ZEOS, то для компиляции надо установить эти компоненты из кодов, которые есть в папке zeosdbo.
А еще проще - обновить (переустановить) компилятор Fpcupdeluxe, в новой сборке которого компоненты ZEOS уже есть. Под Linux это install-fpcupdeluxe-min.run, под Windows - install-daqgroup-fpcupdeluxe-x86.exe.
Доработана функция db_save(dbr,dst,fmt). Теперь она работает для движков SQLDB и ZEOS.
if db_save(dbr,'/tmp/demo.csv',dfAny)
then writeln('Таблица сохранена в файл CSV.');
if db_save(dbr,'/tmp/demo.txt',dfAny)
then writeln('Таблица сохранена в файл TXT.');
if db_save(dbr,'/tmp/demo.xml',dfAny)
then writeln('Таблица сохранена в файл XML.');Продолжалась доработка движка SQLDB и ZEOS. Работа по поддержке БД всё ближе к условному завершению.
Документация DbApi доведена до сносного (пригодного для использования) вида. Она очень кратка и неполна, но как-то жить можно.
Продолжалась доработка движка SQLDB и ZEOS. Много мелких улучшений, документация пока отстаёт. Её доделаем позже.
Продолжалась доработка движка SQLDB. В основном изменения касались db_ctrl(dbc,‘Properties’). Добавлено много новых свойств. Однако документация к ним еще не доделана. Документацию будем дописывать в конце доработки движков DbApi.
Продолжалась доработка движка SQLDB.
В диалог Database Browser добавлена вкладка Info. В ней кнопки для получения инфформации о движке и соединении.
Проводилась доработка движка SQLDB.
В диалог Database Browser добавлена кнопка ODBC. Под Windows она вызывает утилиту настройки источников данных odbcad32.exe. Под Lonux пока не реализовано.
В пакет добавлен движок ZEOS на библиотеке zeosdbo. Идентифицируется константой db_engine_zeos.
Движок по возможностям примерно такой же как SQLDB.
Оба движка SQLDB и ZEOS работают устойчиво, но требуют дополнительной проверки и ряда мелких доработок.
В пакет добавлены исходные коды дистрибутива библиотеки zeosdbo.
ZEOSDBO или просто ZEOS - еще одна популярная библиотека для подключения баз данных. На ней будет работать движок ZEOS библиотеки DbApi.
Необходимость добавления исходных кодов ZEOS связана с тем, что этот пакет не входит в Lazarus по умолчанию и должен устанавливаться отдельно.
Поскольку ZEOS не входит в Lazarus по умолчанию, обновлена сборка fpcupdeluxe с включением компонентов ZEOS в среду Lazarus.
Это нужно для компиляции нового движка баз данныых на основе ZEOS.
Проведена доработка библиотеки DbLibrary.
Поскольку теперь у нас есть несколько движков (ADO,SQLDB), введены функции для задания и определения текущего движка, с которым работает данная прикладная программа.
Процедура db_engine_uses_assign(engine)
задает текущий движок (engine) из набора
(db_engine_ado,db_engine_sqldb).
Рекомендуется помещать вызов этой процедуры в коде инициализации
прикладной программы, чтобы задать программе нужный движок.
Функция db_engine_uses возвращает
заданный процедурой db_engine_uses_assign идентификатор
движка. Функции библиотки DbLibrary и код прикладной
программы должны использовать эту функцию для
определения текущего используемого движка.
Функция
db_validate_known_providers(constr) служит
для коррекции строки подключения в зависимости от текущего движка и
операционной системы. Так, например, для подключения в
Windows с движком ADO используется
провайдер Provider=MSDASQL;Driver=Firebird/Interbase
ODBC;, в то время как в Linux с движком
SQLDB используется Provider=IB;.
Функция умеет переводить строку подключения ADO в
строку подключения SQLDB для некоторых известных
провайдеров (Firebird,SQLight3,PostgreSQL). Кроме того,
функция корректирует (адаптирует) имя файла базы данных для
использования в текущей операционной системе.
Например:
// В начале программы:
// Назначаем используемый движок SQLDB
db_engine_uses_assign(db_engine_sqldb);
// Задаем строку подключения и корректируем её
constr:='Provider=SQLite3;DBName=c:\demo\test.db';
constr:=db_validate_known_providers(constr);
// В процессе работы программы:
// Создаем подключение с текущим движком
con:=db_connection(db_engine_uses,constr);Также добавилось много функций для преобразования данных - смотрите описание.
Скорректированы тесты @Test 12,13,14,16 для проверки функций DbApi для работы с базами данных. Вроде бы всё работает под Win32,Linux с движками ADO,SQLDB.
Скорректирован пример demo_dbquery для работы под Windows,Linux с движками ADO,SQLDB. Пришлось немного поправить код - для корректной работы при вставке/удалении/обновлении записей нужно использовать транзакции (в старой версии транзакции явно не использовались). Вроде теперь всё работает.
Доработан сервер сохранения данных &FdbSrv для работы под Windows,Linux с движками ADO,SQLDB.
Тестирование проводилось на примере demo_dim_ping. Сервер работает. Напоминаю, он создает суточные файлы с таблицами кривых в формате Firebird (файлы .fdb).
Можно констатировать, что в первом грубом приближении интерфейс для работы с Базами Данных (СУБД) интегрирован в пакет.
Предстоит еще доработать документацию и всё хорошенько
проверить.
Это будет после отпуска.
В DaqPascal добавлена функция db_active.
Она нужна потому что результат вызова db_state зависит от движка, а перегружать прикладное программирование не хочется.
Функция db_state проверяет статус активности подключения или
набора записей.
Объект (соединение,команда,набор записей) активен, если он был успешно
создан и открыт.
Например:
dbc:=db_connection(db_engine_sqldb,'Provider=SQLite3;DBName=c:\demo\test.db');
if db_open(dbc) then begin
dbr:=db_execute(dbc,'select * from DEMO_TABLE');
if db_active(dbr) then
while not db_eof(dbr) do begin
writeln('demo_data = ',db_FieldsAsString(db,'demo_data','r',''));
if db_movenext(dbr) then writeln('next record');
end;
end;В DaqPascal добавлена функция db_engineid, а также
константы db_engine_ado,
db_engine_sqldb для
быстрой идентификации движка, используемого для работы объекта
подключения (connection) DbApi. Изначально
номер движка задается в аргументе при создании подключения вызовом
db_connection.
Например:
// Создать соединение
dbc:=db_connection(db_engine_sqldb,'Provider=SQLite3,Database=/opt/demo.db;');
// Узнать движок
case db_engineid(dbc) of
0: writeln('Негодная ссылка на объект.');
db_engine_ado: writeln('Подключение использует движок ADO');
db_engine_sqldb: writeln('Подключение использует движок SQLDB');
end;Необходимость функции связана с появлением нового (второго) движка SQLDB и необходимостью быстрой идентификации используемого движка в прикладном коде.
В пакет crwdaq добавлен движок SQLDB для программного интерфейса баз данных DbApi.
В ближайшее время будет идти его отладка.
Движок SQLDB поддерживает наиболее распространенные типы БД, включая MSSQL, SQLite, Firebird, Oracle, MySQL, PostgreSQL, ODBC. Через ODBC можно (при наличии драйверов) подключать и другие БД.
Надо сразу отметить найденные особенности (или недостатки) движка SQLDB:
SQLDB работает только синхронно - все вызовы
ожидают результат.
Асинхронный режим не поддерживается.
SQLDB кажется не поддерживает поля
BLOB/TEXT.
Таблицы с такими полями не читаются в SQLDB.
Справедливости ради, ADO тоже с такими полями
сбоит.
Реализация движка SQLDB позволяет работать
только с одним набором записей recordset.
Это не сильное ограничение (обычно и работают с одним набором записей),
но его надо учитывать.
Также надо отметить некоторое усложнение прикладного программирования БД, т.к. теперь при анализе данных надо учитывать тип движка db_engineid.
Первый опыт работы с новым движком SQLDB в целом положительный.
Предстоит большая работа по адаптации прикладных библиотек и имеющихся кодов к новому движку (а точнее к работе с несколькими движками).
Обновлен диалог Database Browser с учетом нового движка SQLDB. Вроде бы он приведен в рабочее состояние и теперь работает с движками ADO и SQLDB.
При доработке диалога движок SQLDB проверен на
SQLite3 и Firebird. Вроде всё
работает.
Однако при чтении таблицы JOB в
employee.fdb возникает исключение
Exception «EDatabaseError» hint «Unknown field type : LANGUAGE_REQ» from «TSqlDbConnecter» note «Execute».
Причиной являются поля BLOB/TEXT (двоичные данные),
которые движок не знает как обрабатывать.
Будем пытаться исправить эту ошибку.
Начат процесс обновления документации для нового движка SQLDB. Это потребует времени. Доработка документации будет идти параллельно с отладкой.
В пакет crwkit добавлена отладочная утилита lsdbcl - list database client libraries.
Утилита lsdbcl служит для поиска информации о клиентских библиотеках поддержки СУБД.
Например:
# Список клиентских библиотек СУБД
$ unix lsdbcl -l
[Database Client Libraries]
/lib/x86_64-linux-gnu/libpq.so.5
/lib/x86_64-linux-gnu/libpq.so.5.15
/lib32/i386-linux-gnu/libodbc.so
/lib32/i386-linux-gnu/libodbc.so.2
/lib32/i386-linux-gnu/libodbc.so.2.0.0
/lib/x86_64-linux-gnu/libodbc.so
/lib/x86_64-linux-gnu/libodbc.so.1
/lib/x86_64-linux-gnu/libodbc.so.2
/lib/x86_64-linux-gnu/libodbc.so.2.0.0
/lib/x86_64-linux-gnu/libmysqlclient.so
/lib32/i386-linux-gnu/libsqlite3.so.0
/lib32/i386-linux-gnu/libsqlite3.so.0.8.6
/lib/x86_64-linux-gnu/libsqlite3.so
/lib/x86_64-linux-gnu/libsqlite3.so.0
/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6
/lib/x86_64-linux-gnu/libfbclient.so
/lib/x86_64-linux-gnu/libfbclient.so.2
/lib/x86_64-linux-gnu/libfbclient.so.3.0.11
# Список известных провайдеров СУБД (т.е. типов БД)
$ unix lsdbcl -p
[Database Providers]
MSSQL = "Microsoft SQL" => libsybdb.so
Sybase = "Sybase SQL" => libsybdb.so
PQ = "Postgre SQL" => libpq.so
Oracle = "Oracle" => libociei.so libclntsh.so
ODBC = "ODBC" => libodbc.so
MySQL40 = "MySQL 4.0" => libmysqlclient.so libmysqlclient.so.12 libmysqld.so
MySQL41 = "MySQL 4.1" => libmysqlclient.so libmysqlclient.so.14 libmysqld.so
MySQL50 = "MySQL 5.0" => libmysqlclient.so libmysqlclient.so.15 libmysqld.so
MySQL51 = "MySQL 5.1" => libmysqlclient.so libmysqlclient.so.16 libmysqld.so
MySQL55 = "MySQL 5.5" => libmysqlclient.so libmysqlclient.so.18 libmysqld.so
MySQL55 = "MySQL 5.5" => libmysqlclient.so libmysqlclient.so.18 libmysqld.so
MySQL56 = "MySQL 5.6" => libmysqlclient.so libmysqlclient.so.18 libmysqld.so
MySQL57 = "MySQL 5.7" => libmysqlclient.so libmysqlclient.so.20 libmysqld.so
MySQL80 = "MySQL 8.0" => libmysqlclient.so libmysqlclient.so.21 libmysqld.so
SQLite3 = "SQLite3" => libsqlite3.so
IB = "Interbase/Firebird" => libfbclient.so libgds.so libfbembed.so
# Информация о настройках и драйверах ODBC
$ unix lsdbcl --odbc
[ODBC OPTIONS]
VERSION = unixODBC 2.3.11
DRIVERS = /etc/odbcinst.ini
SYSTEM DATA SOURCES = /etc/odbc.ini
FILE DATA SOURCES = /etc/ODBCDataSources
USER DATA SOURCES = /home/alex/.odbc.ini
SQLULEN Size = 8
SQLLEN Size = 8
SQLSETPOSIROW Size = 8
[ODBC DRIVERS]
PostgreSQL ANSI
PostgreSQL Unicode
FreeTDS
[ODBC DRIVERS FILES]
PostgreSQL ANSI = /lib/x86_64-linux-gnu/odbc/psqlodbca.so
PostgreSQL Unicode = /lib/x86_64-linux-gnu/odbc/psqlodbcw.so
FreeTDS = /lib/x86_64-linux-gnu/odbc/libtdsodbc.so
[ODBC SETUP FILES]
PostgreSQL ANSI = libodbcpsqlS.so
PostgreSQL Unicode = libodbcpsqlS.so
FreeTDS = libtdsS.so
# /etc/odbcinst.ini
[PostgreSQL ANSI]
Description=PostgreSQL ODBC driver (ANSI version)
Driver=psqlodbca.so
Setup=libodbcpsqlS.so
Debug=0
CommLog=1
UsageCount=1
[PostgreSQL Unicode]
Description=PostgreSQL ODBC driver (Unicode version)
Driver=psqlodbcw.so
Setup=libodbcpsqlS.so
Debug=0
CommLog=1
UsageCount=1
[FreeTDS]
Description=TDS driver (Sybase/MS SQL)
Driver=libtdsodbc.so
Setup=libtdsS.so
CPTimeout=
CPReuse=
UsageCount=1
# /etc/odbc.ini
(empty)
# /home/alex/.odbc.ini
(empty)Полезность утилиты lsdbcl в том, что она позволяет быстро находить информацию о клиентских библиотеках для поддержки СУБД, что является важным делом при работе с базами данных.
Утилита findlibso в текущей реализации имела ряд
недостатков. Дело в том, что вызов findlibso базируется
на анализе вывода ldconfig -p, который
возвращает только зарегистрированные файлы библиотек
(кэш загрузчика ld). Но всё обстоит несколько сложнее,
с учетом символических ссылок. Например, есть библиотека
libsqlite3.so.0.8.6 с текущей версией клиентской
библиотеки SQLite3. Для неё (при инсталляции) создается
символическая ссылка libsqlite3.so.0 - это, типа,
текущая версия библиотеки. Именно она зарегистрирована в системе и
выдается в команде ldconfig -p. А кроме
того, для работы клиентских приложений нужно (ручками) создать
символическую ссылку libsqlite3.so без номера версии -
это, типа, рабочая версия библиотеки, на которую обычно ссылаются
клиентские программы. Однако хотя эти (дополнительные) файлы не
зарегистрированы в системе явно, загрузчик ld их видит.
Например, вызов
LoadLibrary('libsqlite3.so') будет
успешным, хотя файла libsqlite3.so в списке регистрации
нет. Видимо, загрузчик сам находит файлы в каталогах, где находятся
зарегистрированные библиотеки. Таким образом, надо различать явно
зарегистрированные библиотеки и все библиотеки, доступные в
зарегистрированных в системе библиотечных каталогах (назовем их
доступными библиотеками). Поэтому надо снабдить утилиту
findlibso дополнительными опциями.
unix findlibso -h или --help # справка
unix findlibso -l или --list # список зарегистрированных библиотек (имя версия => путь)
unix findlibso -p или --path # список зарегистрированных библиотек (только полный путь)
unix findlibso -d или --dirs # список каталогов для всех зарегистрированных библиотек
unix findlibso -f или --find # список всех доступных библиотек в зарегистрированных каталогах
unix findlibso -f sqlite3 # поиск (всех) доступных библиотеки по имени (шаблону)
unix findlibso libsqlite3.so # поиск (лишь) зарегистрированных библиотек по шаблонуНапример:
# получить список зарегистрированных библиотек по имени (шаблону)
$ unix findlibso sqlite3
/lib/x86_64-linux-gnu/libsqlite3.so.0
/lib32/i386-linux-gnu/libsqlite3.so.0
# получить список (всех) доступных библиотек по имени (шаблону)
$ unix findlibso -f sqlite3
/lib32/i386-linux-gnu/libsqlite3.so.0
/lib32/i386-linux-gnu/libsqlite3.so.0.8.6
/lib/x86_64-linux-gnu/libsqlite3.so
/lib/x86_64-linux-gnu/libsqlite3.so.0
/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6В нашем конкретном случае библиотека libsqlite3.so была получена командой:
$ sudo ln -s -T /lib/x86_64-linux-gnu/libsqlite3.so.0 /lib/x86_64-linux-gnu/libsqlite3.soТо есть она указывает (символичекой ссылкой) на libsqlite3.so.0.
Такая сложная система загрузчика сделана для того, чтобы была возможность выбора библиотек при наличии нескольких версий библиотек. Клиентская программа может ссылаться на:
Поскольку рабочая и текущая версия библиотеки являются символическими ссылками, их можно легко заменить при смене конкретной версии библиотеки (которых может быть даже несколько). При этом клиентская программа будет работать по-прежнему. Но если программа использует какие-то особенности конкретной версии библиотеки, то есть возможность найти нужную загружаемую библиотеку, если использовать полное имя библиотеки (с номером версии).
Таким образом, используя эту сложную систему поиска, загрузчик дает возможность гибкого управления библиотеками даже при наличии нескольких версий библиотек.
Проект sqldbtest включен в группу проектов crwkit.lpg, которая включает в себя все проекты в рамках crwdaq suite.
В программе crwdep добавлены пакеты поддержки ODBC.
sudo apt install unixodbc odbcinst tdsodbc odbc-postgresql unixodbc-devODBC - это библиотека унифицированного доступа к базам данных. Для них ещё нужны клиентские библиотеки ODBC. В AstraLinux репозитории есть клиентские библиотеки ODBC для PostgreSQL и MSSQL. Библиотеки для остальных СУБД надо искать отдельно.
В библиотеку crwlib добавлена
функция CookieScanAlter(Buff,Items,Mode).
Она отличается от функции
CookieScan(Buff,Name,Mode) возможностью
альтернативного выбора имен из списка Items,
разделенного символами запятой (,) или точки с запятой
(;).
Например:
// Буфер для чтения
Buff:='Provider=ADODB;UserName=Master;';
// Чтение переменной с именем UserName
UserName:=CookieScan(Buff,'UserName',Ord(';'));
// Чтение переменной UserName, или User ID, или UID.
UserName:=CookieScanAlter(Buff,'UserName;User ID;UID',Ord(';'));Чтение параметров с альтернативой выбора используется для анализа
строк описания подключения к базам данных. Различные
СУБД используют разные имена для описания параметров
подключения. Например, имя пользователя может быть задано переменными с
альтернативным набором имен: UserName, User
ID или UID. Вызов типа
UserName:=CookieScanAlter(Buff,'UserName;User ID;UID',Ord(';'));
позволяет прочитать параметр с альтернативным набором имен одним
вызовом, вместо целого блока кода с тремя вызовами
CookieScan для каждого альтернативного варианта.
Также функция CookieScanAlter добавлена в StdLib. Эта функция (на данный момент) является не вызовом, а независимой реализацией того же алгоритма на DaqPascal. Однако она должна работать так же как функция из crwlib.
В Test 21 программы demo_testbench добавлена проверка работы функции CookieScanAlter.
Одной из нерешенных проблем остается поддержка СУБД под Linux.
В среде Lazarus есть несколько библиотек для поддержки СУБД.
Пока что для реализации поддержки СУБД под Linux и Windows принято решение взять SQLDB. Причина именно в том что пакет SQLDB доступен по умолчанию. Посмотрим, что из этого получится.
Для разработки и тестирования библиотек поддержки СУБД сделана “песочница” - проект sqldbtest. На этом проекте будут пробоваться и отлаживаться библиотеки поддержки СУБД в процессе разработки.
Пока сделан простейший тест чтения файла базы данных SQLite3. Разработка библиотек ведется под Windows (так пока удобнее). Но и под Linux тест тоже работает.
Согласно документации, для работы библиотек поддержки СУБД нужны клиентские динамические библиотеки - своя библиотека для каждого типа СУБД.
Вот некоторые библиотеки под Linux:
| СУБД | Библиотека | Пакет APT |
|---|---|---|
| SQLite3 | libsqlite3.so | sqlite3 |
| Firebird | libfbclient.so | libfbclient2 |
| PostgreSQL | libpq.so | libpq5 |
Однако при запуске тестовой программы sqldbtest под
Linux выдавалась ошибка
“Не найдена библиотека libsqlite3.so”,
хотя пакет sqlite3 был установлен. Исследование с
помощью утилиты unix findlibso (см. описание ниже)
показало, что причиной проблемы является именование библиотеки. А
именно, библиотека поддержки SQLite3 имеет имя
libsqlite3.so.0 с номером версии на конце.
Проблема решилась созданием символической ссылки libsqlite3.so, которая указывает на libsqlite3.so.0. После создания такой ссылки всё заработало.
Это, по всей видимости, общее правило. Файлы клиентских библиотек именуются с номером версии, а для использования в конкретной среде надо делать символические ссылки на эти библиотеки. Это надо иметь в виду при настройке систем.
В пакет crwlib добавлена утилита
findlibso. Она служит для поиска общих
динамических библиотек lib*.so,
зарегистрированных в системе. Это полезная утилита, т.к. библиотек много
и они “разбросаны” по многим каталогам. Регистрация библиотек в системе
делается с помощью программы ldconfig. Утилита
findlibso основана на её использовании.
unix findlibso -h # справка
unix findlibso -l # список библиотек (имя, версия => путь)
unix findlibso -p # список библиотек (путь)
unix findlibso libsqlite3.so # поиск библиотеки по имени (полному)
unix findlibso sqlite3 # поиск библиотеки по имени (неполному)Утилита findlibso будет полезна для конфигурирования системы, где будут так или иначе использоваться СУБД.
Обновлена утилита unix crwdep для
проверки списка зависимостей crwdaq.
В список зависимостей добавлены некоторые клиентские библиотеки поддержки СУБД.
В большом числе файлов ДЕМО конфигураций сделаны исправления .DAT,.CRW на .dat,.crw. Это влияет на корректную работу диалогов открытия .dat файлов.
Переведена (из старой версии) ДЕМО конфигурация demo_birger.
Продолжена разработка драйвера LCARD E140/E440. Сервер сбора данных уже как-то работает, но механизм передачи через общую память пока еще не реализован. Чтобы не потерять версии черновых ДЕМО конфигураций, заведена папка demo/draft. Там будут располагаться черновики конфигураций до их перевода в рабочее состояние.
Переведена (из старой версии) ДЕМО конфигурация demo_hvss (высоковольтная система сканирования HVSS). Она переведена “как есть”, без серьезной модификации и проверена в режиме симулятора. Вроде бы всё работает нормально.
Примечание. При переводе конфигурации на мнемосхемах “сбились” шрифты, т.к. использовались Windows шрифты Arial, Courier New. Их надо заменять на (соответственно) PT Sans, PT Mono.
Описаны шрифты, используемые для кроссплатформенной разработки. А также рекомендованные замены шрифтов при переводе.
Переведена (из старой версии) ДЕМО конфигурация demo_vmcd.
Переведена (из старой версии) ДЕМО конфигурация demo_vtrd.
В процессе тестирования на стенде ошибка WatchdogDeadline возникла снова. Значит, её причина еще не устранена.
Предпринята еще одна попытка решить эту проблему. Для этого переменная TProgramDevice.WatchdogStarted была защищена критической секцией. Эта переменная используется в двух потоках и в принципе возможен конфликт доступа. Дальнейшие тесты покажут, в этом ли дело.
Добавлен модуль StdMenuTools для меню Инструменты. Смотрите описание и коды.
В стандартную библиотеку добавлена группа функций для поддержки языка графического интерфейса. Это функции GuiLanguageSign, GuiLanguageCode, glc_Russian, glc_English, RusEngStr.
Добавлена полезная функция общего применения IfThenStr.
Добавлена процедура StdSensorHelpTooltip для отображения справки по правой кнопке сенсора.
Большинство demo конфигураций переделаны использованием StdSensorHelpTooltip. Это позволило убрать из программ избыточно громоздкие конструкции при вызове ShowTooltip.
Стандартная справочная процедура для справки по правой кнопке сенсора теперь выглядит примерно так:
{
Procedure to show sensor help
}
procedure SensorHelp(s:String);
begin
StdSensorHelpTooltip(s,15000);
end;Шаблон программы в DaqCreator модифицирован с использованием StdMenuTools, StdSensorHelpTooltip.
То есть новые системы будут создаваться с учетом этих новшеств.
Как выяснилось в процессе анализа ситуации с обнулением файлов в конфигурации demo_wj300a, причиной была не проблема в функции f_close (это просто место обнаружения проблемы), а функция FileCopy.
А именно, при совпадении имени файла источника и приемника, файл источника обнуляется при вызове FileCopy. Такое поведение наблюдается только в версии Linux. Это, видимо, особенность реализации функции на уровне системы.
Для устранения проблемы в функциях FileCopy, FileRename введена проверка IsSameFileName(…) для имен файлов источника и приемника. Если файл источника и премника совпадают, копирование отменяется и возвращается False.
Проблема решена на уровне библиотеки crwlib, т.е. во всех программах DaqGroup.
Добавлена (с мелкими доработками) ДЕМО конфигурация demo_akip. Это драйвер осциллографа AKIP от А.Пергаева. Хорошая работа.
Добавлена конфигурация demo_wj300a для драйверов LeCroy WJ300A.
В процессе перевода сценария генератора из wj300a_devices.cmd в wj300a_devices.sh зафиксирована (очень кратко) процедура перевода и таблица замен (регулярных выражений) для ускорения процесса перевода.
При тестировании demo_wj300a была найдена ошибка в реализации функции WordDelims. А именно, вызов WordDelims(Dump(0)) работал с ошибкой, из-за чего фрагмент
sNul(worddelims(' '));
v:=ExtractWord(2,arg);
sNul(WordDelims(Dump(0)));работал неверно - вместо восстановления начальных значений разделителей слов он устанавливал неверный разделитель, что приводило в дальнейшем к массовым сбоям программы, т.к. функции анализа строк типа ExtractWord переставали корректно работать.
Причиной ошибки оказался безобидный на первый взгляд вызов Dump(0) в коде компилятора DaqPascal. Дело в том, что в библиотеке crwlib функция Dump является “перегруженной” (overload), то есть для каждого типа данных работает своя функция. С учетом этого обстоятельства вызов Dump(0) является, строго говоря, неоднозначным, т.к. не уточняется точный тип нуля, а ведь он может быть разным, например, byte, word, longint, int64 и т.д. Обычно это не играет роли в арифметике, т.к компилятор автоматически приводит ноль к нужному типу, исходя из типа результата или операндов. Но в данном конкретном контексте тип нуля важен, т.к. это число преобразуется в строку “дампа”.
На самом деле в коде подразумевалось, конечно Dump(Integer(0)). По всей видимости, компилятор вместо этого использовал какой-то другой целочисленный тип нуля, что и приводило к ошибке. Таким образом, неоднозначность интерпретации типа нуля повлекла за собой ошибку. К компилятору претензий нет, это был очевидный недостаток кода. Код должен интерпретироваться однозначно. Если результат зависит от неявной трактовки, это ошибочный код.
После замены Dump(0) на Dump(Integer(0)) ошибка исчезла.
Лишний раз убеждаемся в коварстве неявного преобразования типов. Нужно быть внимательным.
Заметим, что в прикладных программах DaqPascal вызов Dump(0) однозначен, т.к. в DaqPascal есть только один целочисленный тип integer, эквивалентный longint. То есть в DaqPascal вызов Dump(0) является вполне корректным.
Исправлена замеченная Н.Гуриным небольшая проблема в процедуре read_proc_pid_file, заключающаяся в возникновении исключений EFOpenError при открытии файлов /proc/pid/status. Проблема в том, что при проверке статуса процесса из списка процесов этот процесс может завершиться в промежутке между проверкой его существования и открытием файла. В этом случае возникает исключение. Хотя в принципе это ситуация вполне нормальная - процессы могут возникать и завершаться в любой момент. Исправление ошибки заключается в перехвате и игнорировании этого исключения, т.к. нет оснований считать его ошибкой и выводить диагностику.
При тестировании конфигурации demo_wj300a обнаружена странная ошибка. Она проявляется только в Linux версии и касается функции f_close.
При вызове функции сохранения данных в файл .csv или .osc вызовы f_rewrite, f_write проходят успешно. Это видно по возвращаемому значению, а также по тому, что файл создается и имеет ненулевой размер в процессе записи. Однако при вызове f_close размер файла обнуляется. Это выглядит так, будто файл был обрезан.
Причина ошибки пока не найдена.
Улучшена диагностика ошибок в компиляторе и редакторе DaqPascal. Теперь при ошибке во включаемом файле в Главную Консоль выдается список исходных файлов с положением ошибки. Это позволяет проследить местоположение ошибки в случае использования включаемых файлов.
Например:
2025.05.19-19:04:23 => Ошибка компиляции 1
Файл: /home/alex/daq/test/daqpas/test_main_ctrl.pas
Причина: Attempt at multiple definition
Строка: 54
Колонка: 21
Список Исходных Файлов:
Строка Столбец Файл
54 21 /home/alex/daq/test/daqpas/test_main_ctrl.pas
26 19 /mnt/data/home/alex/projects/daqgroup/suite/crwdaq/resource/daqsite/stdlib/include/_fun_stdlibrary.inc
21 15 /home/alex/daq/test/daqpas/_fun_stdutils.incУлучшенная диагностика ошибок поможет быстрее находить ошибки в исходном тексте и облегчит их исправление.
Обновление DaqCreator от Н.Гурина. Добавлено меню редактирования программ и перезапуска DAQ-устройств.
Права для редактирование программ DaqPascal повышены до уровня Root. Таблица прав содержится в файле crwdaq.guard.ini.
Список замечаний и предложений crwdaq-todo.htm служит для того чтобы не забыть исправить замеченные недоработки или добавить предложенные улучшения.
Реализована опция guid в утилите
unix tooltip-notifier. Эта опция служит
для замены всплывающего сообщения с заданным идентификатором
guid на месте старого окна (без появления нового окна
сообщения). Это нужно для борьбы со “спамом” - избыточным числом
всплывающих сообщений. Опция работает (под Linux)
только с системой уведомлений dunst.
Для проверки и демонстрации работы опции guid можно набрать в терминале Linux команду:
for i in $(seq 1 10); do unix tooltip-notifier guid demoTest text "Demo: $(date)" preset stdnotify delay 300000; echo $i; sleep 1; done;При работе этой команды появится окошко, в котором в течение 10 секунд будет меняться время (без создания новых окон).
Для сравнения можете запустить команду без опции guid:
for i in $(seq 1 10); do unix tooltip-notifier text "Demo: $(date)" preset stdnotify delay 300000; echo $i; sleep 1; done;Также в целях оптимизации в утилите tooltip-notifier
сделана замена выражений [ … ] на
[[ … ]]. В интернетах пишут, что вроде бы
двойные скобки работают быстрее, поскольку являются встроенными
функциями bash, а не вызовом внешней программы
test.
При тестировании на испытательном стенде были обнаружены непонятные сбои DaqPascal с кодом ошибки 8 (ExternalBreak). Этот код однозначно указывает на внешнее прерывание от сторожевого таймера в процедуре TProgramDevice.Watchdog. Сбои возникали эпизодически (очень редко) и без явно видимой причины.
Пример сообщения (консольный вывод):
2025.04.21-16:23:15 => Exception «EDaqPascalRuntimeError» in crwdaq PID 221040
2025.04.21-16:23:15 => Exception «EDaqPascalRuntimeError» from «TDaqPascal» note «&MODBUSPROXY: Halted at 31240 because of external break 15.»
2025.04.21-16:23:15 => Exception «EDaqPascalRuntimeError» hint «Daq Pascal Runtime Error 8, opcode 18»
2025.04.21-16:23:15 => Exception at 000000000183C1D8: EDaqPascalRuntimeError: Daq Pascal Runtime Error 8, opcode 18.
&MODBUSPROXY ! Program terminated because too many exceptions occured: Counter = 1.
&MODBUSPROXY ! Some fatal error(s) occured, like out of range, divizion by zero, etc.
&MODBUSPROXY ! Program terminated because too many watchdog DEADLINEs: Counter = 1.
&MODBUSPROXY ! Some fatal error(s) occured, like infinite while loop, long waits etc.
&MODBUSPROXY ! Please restart the program (@compile device &), or restart DAQ system.
&MODBUSPROXY ! **********************************************************************
&MODBUSPROXY ! Abnormal termination. Please restart the device or restart DAQ system.
&MODBUSPROXY ! **********************************************************************
DAQ SYSTEM WARNING: WATCHDOG DEADLINE DETECTED.
No reply from device &MODBUSPROXY during 63880849395.954 sec. Deadline is 60.000 sec.
@tooltip text "2025.04.21-16:23:15 - crwdaq#1/221040@test-stand: Failure on Device &MODBUSPROXY." preset stdError delay 86400000
@compile device &MODBUSPROXY
2025.04.21-16:23:16 => Успешная компиляция
Файл: /mnt/data/home/main/projects/daqgroup/suite/crwdaq/resource/daqsite/modbusserver/modbusproxy.pasСообщения указали на модули _crw_daqpascaldevice и _crw_daqpascalcompiler (ключевое слово WatchdogStarted). Анализ кода позволил выдвинуть гипотезу, что сбой происходит из-за разницы в деталях реализации mSecNow и IntMSecNow, которые молчаливо предполагались идентичными (хотя в реальности немного отличаются типами результата). Кроме того, IntMSecNow имел беззнаковый тип QWord, хотя в расчетах везде использовались знаковые переменные Int64 или Double. Поэтому были предприняты следующие меры:
Поможет ли это - посмотрим…
В demo добавлена конфигурация test_stand. Это слегка поправленная конфигурация со стенда для тестирования пакета.
В последнем шаблоне DaqCreator были добавлены меню
@MenuToolsOpen - open Menu Tools dialog. # Меню Инструменты (Tools)
@MenuConsolesOpen - open consoles menu # Меню Открыть консольные окна
@MenuEditProgramOpen - open edit program menu # Меню Редактировать программу
@MenuDeviceRestartOpen - open device restart menu # Меню Перезапустить программуЭти меню добавлены в конфигурации demo_opcuamon, demo_dim_ping, которые можно использовать как пример (шаблон) реализации меню для других DAQ систем.
Указанные команды полезны для разработки и поддержки DAQ систем, поэтому есть смысл добавлять их и в другие разрабатываемые системы.
Проводились мелкие доработки opcuamon.pas. В частности,
Сделана программа opcuasrv.pas - оболочка для сервера opcuasrv.py. Эта программа завершает работу по созданию сервера OPCUA в пакете crwdaq. Имеется справка opcuasrv.htm.
Сервер &OpcuaSrv и монитор &OpcuaMon созданы и работают, но еще требуют “шлифовки”, т.е. доработки различных деталей реализации. Эта работа будет продолжаться в ближайшее время.
Дополнена демо конфигурация demo_opcuamon. В ней к имеющемуся монитору &OpcuaMon добавлен сервер &OpcuaSrv, так что теперь пример иллюстрирует работу как клиента, так и сервера OPCUA.
Сделано обновление DaqCreator, предоставленное Н.Гуриным.
Там добавлена поддержка кроссплатформенных сценариев (cmd, sh), а также меню “Открыть меню консолей” для того, чтобы иметь возможность быстро открыть консольные окна DAQ-устройств из меню инструментов. Это весьма полезная возможность.
При анализе кода было обнаружено, что команда @MenuToolsOpen была переименована в @OpenToolsMenu. Было решено переименовать её обратно, вернув старое значение @MenuToolsOpen. Это было сделано из соображений обратной совместимости. Дело в том, что в каталоге demo, например, есть десятки систем, которые используют коды с командой @MenuToolsOpen. Эта команда напрямую “завязана” на мнемосхемы и сообщения. Необоснованное переименование создает путаницу на пустом месте, особенно при редактировании старого кода, который “смешивается” с новым кодом. Этой путаницы можно легко избежать, сохраняя старые названия.
Общий принцип состоит в том, что старый (даже несовершенный) код лучше не трогать (имеется в виду внешний интерфейс вызова). Если добавляется существегнно новый функционал, требующий изменения интерфейса вызова, лучше создать новую функцию или команду.
Так например, в Windows API есть большая группа функций XxxxEx, которая является расширением (extension) функций Xxxx. Например, есть функция FindWindow, а есть функция FindWindowEx с расширенными возможностями (и другим списком аргументов). Расширенные функции вводились именно для того, чтобы получить новый функционал, но без “ломки” кода, использующего старые функции.
По аналогичным причинам команда @OpenConsolesMenu переименована в @MenuConsolesOpen. Лучше придерживаться единого стиля наименования команд.
Сделана программа opcuasrv.py - сервер OPCUA на языке Python. Его работа проверена в консольном режиме. Можно сказать, половина работы для реализации сервера OPCUA сделана. Для интеграции в пакет надо сделать оболочку opcuasrv.pas на DaqPascal. Эта будет задачей на ближайшее время.
Обновлена программа opcuamon.py.
@OpcSubInter p для
задания интервала (периода) обновления подписки.Программную оболочку opcuamon.pas тоже пришлось
доработать для поддержки команды
@OpcSubInter p.
Обновлена программа opcuamon.py. В ней добавлена
поддержка строковых индексов, наряду с численными.
Например:
ns=2;i=2023 # численный индексный идентификатор
ns=2;s=Tag32 # строковый индексный идентификатор
ns2i2023 # численный индексный идентификатор (короткий)
ns2sTag32 # строковый индексный идентификатор (короткий)Соответственно обновлена программа - оболочка opcuamon.pas.
В пакет crwkit добавлена утилита dirchain. Эта утилита печатает цепочку (последовательность) родительских каталогов для аргумента - каталога или файла.
Например:
$ unix dirchain /usr/share/applications/firefox.desktop # вывод цепочки родительских каталогов для файла
/usr/share/applications
/usr/share
/usr
$ unix dirchain /usr/share/applications 2 # вывод цепочки каталогов с ограничением по глубине
/usr/share/applications
/usr/share
$ unix -t dirchain /usr/share/applications # вывод цепочки каталогов в другом порядке
/usr
/usr/share
/usr/share/applications
$ unix -d dirchain /usr/share/applications # вывод глубины цепочки каталогов
3Утилита полезна для создания сценариев для обработки каталогов.
Например:
# Задать права на чтение и обзор каталога и его родителей
$ unix dirchain /opt/demo/test | xargs -n1 | chmod -с ugo+rxИсправлена указанная Н.Гуриным ошибка в документации devsend, devsendmsg. Ошибка была в типе возвращаемого результата функций. По число историческим причинам это тип real, а не integer.
В инсталлятор firefox добавлены сертификаты МинЦифры, которые нужны для удостоверения на многих сайтах. Без этих сертификатов некоторые сайты не работают.
Сразу в нескольких инсталляторах сделаны мелкие поправки, связанные с правами доступа к папкам и файлам. В основном это устранение проблем с файлами, к которым не было прав доступа у ограниченного пользователя из-за неверной установки chmod. Замеченные ошибки такого рода были устранены.
Добавлен инсталлятор install-daqgroup-firefox.run.
Это самая свежая версия Firefox с сайта
Mozilla в виде архива
*.tar.xz, плюс инсталлятор на
bash.
Установка производится в каталог /opt/mozilla/firefox/, при
этом оригинальная инсталляция не затрагивается. Также заменяется
символическая ссылка /usr/bin/firefox и
файл ярлыка firefox.desktop.
Оригинальная версия браузера остается доступной по команде
firefox-old.
Несмотря на изменение расположения Firefox, всё
остальное остается прежним, т.к. большинство программ ссылается либо на
короткую команду firefox, либо на
/usr/bin/firefox, которые ссылаются на
место инсталляции новой версии. Поэтому по команде
firefox вызывается новая версия браузера.
Старая версия браузера вызывается командой
firefox-old.
Необходимость введения нового инсталлятора связана с устареванием Firefox, входящего в репозиторий, при этом некоторые вещи (например, сертификаты безопасности) перестают работать, что неизбежно отражается на функциях отображения содержимого Веб страниц. Инсталлятор install-daqgroup-firefox позволяет установить свежую версию firefox, не затрагивая штатную инсталляцию.
Чтобы “отменить” новую версию, и вернуться к старой, достаточно
скопировать или переименовать ссылку
/usr/bin/firefox-old в
/usr/bin/firefox, т.е. вернуть старую
символическую ссылку на прежнее место. При этом новую версию
Firefox в папке /opt/mozilla/firefox
удалять не обязательно.
В пакет crwkit добавлена программа ansi. Она предназначена для цветной печати в консоли. Полезна для сценариев bash. К программе прилагается ansiman - команда для обзора справки.
Примеры:
unix ansi -n --bold --red "Error"; unix ansi " found.";
unix ansi -n --bold --bg-white-intense --blue "Information"; unix ansi " message.";Вывод:
Error found. Information message.
Программа ansiman:
unix ansiman; # открыть файл справки
unix ansiman --path; # путь файла справки
unix ansiman --version; # версия утилитыНа панели инструментов Главного Окна добавлены
кнопки
- менеджер устройств DAQ,
-
главное окно DAQ. Добавление связано с тем, что это
наиболее часто используемые при разработке команды, которые удобно иметь
под рукой. Также немного изменена экранная привязка диалога менеджера
устройств DAQ.
Изменены процедуры вызова справки (F1). Это связано с тем, что в бывшей до этого процедуре использовалась команда xdg-open, которая зависит от настроек файловых ассоциаций. При изменении ассоциаций вместо вызова браузера (обычно firefox) может быть вызвана другая программа, что нежелательно. В новой версии файл справки всегда открывается браузером.
Завершена работа над монитором opcuamon - по крайней мере на данном цикле развития.
Доработке подверглись алгоритмы автоматичекого обновления (записи) данных. В предыдущей версии корректно было реализовано только автоматическое чтение данных, а также чтение и запись по событиям (посылкой сообщений).
Для автоматической записи изменений потребовалось доработать механизм триггера, который запускает запись при изменении данных. При этом, поскольку меняться могут разные характеристики данных (координата x или y подключенной кривой, значение подключенного тега), то необходимо указывать и учитывать источник триггера.
По результатам имеем монитор (клиент) OPCUA общего назначения, позволяющий читать/записывать данные с частотой до (примерно) 1000 узлов в секунду.
В планах - создание сервера OPCUA общего назначения, чтобы уже окончательно завершить эту тему.
Сделан файл default.htm с описанием конфигураций для параметров и серверов по умолчанию.
Ссылка на него также добавлена в основной справочный файл.
Доработана справка по opcuamon.
Также в библиотеку добавлена конфигурация default/opcuamon.cfg. Это конфигурация “по умолчанию” для монитора &OpcuaMon для связи с сервером OPCUA. Поскольку серверов OPCUA и подключенных к ним мониторов может быть несколько, добавлены конфигурации “по умолчанию” для дополнительных мониторов &OpcuaMon1, &OpcuaMon2, &OpcuaMon3. Это позволяет подключать до 4 серверов OPCUA. При необходимости число дополнительных мониторов можно увеличить.
Были исправлены замеченные (мелкие) ошибки в коде оболочки монитора opcuamon.pas.
Также была дополнена справка по программе монитора.
В демо конфигурации demo_opcuamon
добавлен тест производительности OPCUA.
В модели данных сервера заведено 20 узлов TestPerf00 … TestPerf19. Клиент (монитор) подписывается на эти теги. При включении теста производительности программа с заданной частотой посылает запрос на обновление значений узлов на сервере. Клиент фиксирует изменение данных после их обновления на сервере.
Тест показал, что при частоте до (примерно) 1 кГц включительно, т.е. до 1000 обновлений узлов в секунду всё работает нормально, без сильного влияния на частоту цикла опроса монитора и его времени отклика.
При частоте выше 1 кГц частота цикла опроса монитора начинает заметно падать, а время отклика увеличивается. После 1.5 кГц время отклика критически падает, а данные начинают “застревать” в очереди, из-за критического снижения частоты цикла опроса монитора. При этом загрузка потока мониторной программы и программы-оболочки составляет порядка 10 %.
Таким образом, в текущей версии частота обновлений тегов OPCUA ограничена величиной около 1 кГц. Для большого числа относительно простых задач этого вполне достаточно.
Было решено на данном этапе удовлетвориться полученным результатом. Оптимизация, если она потребуется, будет производиться по мере необходимости.
Продолжались работы по demo_opcuamon и
opcuamon.pas. Можно сказать что работа по
созданию монитора сделана на условные 80%.
Пока еще не доработаны такие вопросы:
В инсталляторе, а также в стартовом сценарии crwdaq.logon.sh добавлена установка прав доступа на запись к некоторым папкам и файлам, например, к resource/daqsite/stdlib/bitmaps. Это позволит устранить некоторые ошибки при работе пакета.
Продолжалась работа над demo_opcuamon и
программой opcuamon.
Монитор постепенно оживает и обретает завершенный вид.
Обновление DaqCreator от Н.Гурина.
Начата (но еще не завершена) ДЕМО конфигурация demo_opcuamon.
Конфигурация demo_opcuamon запускает
программу OPCUA сервера demo-wave-server,
которая содержит генератор волны (wave). Сервер написан на
python, модель данных сгенерирована с помощью
opcua-modeler.
Клиент содержит монитор opcuamon.py, а также клиентскую часть opcuamon.pas.
Монитор почти завершен, клиентская часть еще не завершена, но уже
работоспособна.
Планируется завершить работу в ближайшее время.
Существенно обновлены пакеты daqgroup-opcua и daqgroup-pylibs. В частности, добавлен пакет opcua-modeler, который реализует редактор адресного пространства OPCUA. Вместе с утилитой opcua-client, которая позволяет подключаться к любым серверам OPCUA и наблюдать публикуемые ими данные, это дает набор инструментов для создания, изучения, настройки и обслуживания серверов и клиентов OPCUA.
Сделана утилита unix opcua-cpl, которая
выполняет роль Центра Управления OPCUA, то есть единого
центра, из которого можно управлять различными действиями, связанными с
технологией OPCUA: вызывать различные утилиты, смотреть
документацию и т.д. См. /opt/daqgroup/share/opcua/scripts/
Команда unix opcua-cpl menu открывает
меню для вызова всех функций Центра Управления
OPCUA.
unix opcua-cpl opcua-client-gui -
Открыть клиент для обзора OPCUAunix opcua-cpl opcua-modeler-gui -
Редактор адресного пространства OPCUAunix opcua-cpl opcua-client-example -
Запуск тестового клиента opcuaunix opcua-cpl opcua-server-example -
Запуск тестового сервера opcuaunix opcua-cpl opcua-spec-web -
Спецификации OPCUA (обзор)unix opcua-cpl opcua-spec-dir -
Спецификации OPCUA (папка)unix opcua-cpl opcua-articles-web -
Статьи по OPCUA (обзор)unix opcua-cpl opcua-articles-dir -
Статьи по OPCUA (папка)unix opcua-cpl pylibs-articles-web -
Статьи по Python (обзор)unix opcua-cpl pylibs-articles-dir -
Статьи по Python (папка)unix opcua-cpl pycrwkit-readme-web -
Модуль pycrwkit (обзор)unix opcua-cpl pycrwkit-readme-dir -
Модуль pycrwkit (папка)unix opcua-cpl asyncua-doc -
Документация по библиотеке AsyncuaС помощью утилиты unix opcua-cpl menu
реализовано меню Старт/Сеть/Центр Управления OPCUA,
через которое можно вызывать Центр Управления
OPCUA.
Вызов Центра Управления OPCUA добавлен в меню Инструменты/Центр Управления OPCUA пакета crwdaq. Теперь функции поддержки OPCUA будут всегда под рукой.
Создан монитор opcuamon.py, который может подключаться к серверам OPCUA, читать и записывать данные, подписываться на мониторинг по изменению данных. Имеется документация opcuamon.htm. Монитор написан на Python3, использует модули asyncua и pycrwkit. Работает под Linux и Windows. Проверен в консольном режиме на тестах.
Остается написать клиентскую часть на DaqPascal для
включения монитора в состав DAQ системы.
Этому и будет посвящена работа в ближайшее время.
Сделаны мелкие доработки pycrwkit и demo_pycon. Добавлена документация, проведена частичная оптимизация кода.
Сделана утилита readcfg. Она предназначенв для чтения секций или именованных переменных из INI или CFG файлов.
unix readcfg /opt/crwdaq/crwdaq.ini [System] # чтение из crwdaq.ini секции [System]
unix readcfg /opt/crwdaq/crwdaq.ini [System] Language # чтение переменной, вывод key=value
unix readcfg /opt/crwdaq/crwdaq.ini [System] Language -v # чтение переменной, вывод только valueЧтение происходит по правилам DaqConfig, который имеет расширенные возможности. В частности:
Утилита readcfg будет полезна для сценариев конфигурирования или программ, где надо использовать данные из конфигурационных файлов. Важно, что команда readcfg читает файлы по такому же алгоритму, как пакет crwdaq, что позволит избежать разночтений при сложной структуре файлов (с разбиением секциий включением вложенных файлов).
Вот справка по команде:
readcfg version 1.0.
Copyright (c) 2001-2025 DaqGroup daqgroup@mail.ru.
readcfg - read config file.
Purpose:
Read parameters or sections from ini or configuration file.
Expected INI file format:
[Section]
Key = Value
Syntax:
readcfg [-f] cfg [-s] sec [[-k] key]
Options:
-f cfg : set file name (cfg)
-s sec : set section name (sec)
-k key : set key name (key)
-v : print only values
Notes:
Example:
readcfg file.ini [section] - read section
readcfg file.ini [section] key - read key=value
readcfg -f file.cfg -s section -k key - read key=value
readcfg -v -f file.cfg -s section -k key - read only valueДля поддержки разработки консольных драйверов (серверов) на языке Python была разработана библиотека StdPyApp. Читайте описание, не буду повторяться.
Для иллюстрации использования StdPyApp при создании серверных приложений на языке Python была создана конфигурация demo_pycon. Читайте описание, не буду повторяться.
Можно констатировать появление поддержки Python в пакете crwdaq. Пока это сделано в форме внешних (серверных) приложений, хотя в принципе возможна полная интеграция Python в пакет (пока это не планируется). Практика покажет, насколько это будет полезно.
Обновление DaqCreator от Н.Гурина.
Библиотеки на языке python первоначально были собраны для реализации сервера opcua. Однако было решено, что поскольку поддержка python - более широкая тема, чем opcua, будет логично выделить её в отдельный пакет.
В результате был создан пакет daqgroup-pylibs с инсталлятором install-daqgroup-pylibs.run, в который вошли библиотеки python и документация по языку python.
А в пакете daqgroup-opcua остались только материалы, непосредственно касающиеся opcua. Это документация (спецификации), а также библиотеки на различных языках для реализации протокола opcua.
Обновлены инсталляторы под Windows для crwdaq и fpcupdeluxe. Обновление предоставил Н.Гурин.
Для разработки (консольных) приложений для
DAQ-систем была создана библиотека
pycrwkit.
Эта библиотека содержит ряд служебных функций, а также класс
DaqApplication, позволяющий создавать программы
(консольных) приложений для DAQ-систем. Библиотека была
оформлена в виде модуля - файла
*.whl. Для сборки модуля нужно установить
пакет python3-build и запустить build.sh
в каталоге build_pycrwkit:
sudo apt install python3-build
cd /opt/daqgroup/share/pylibs/build_pycrwkit
./build.shГлавное достоинство DaqApplication - это
асинхронный консольный ввод, что позволяет делать
консольные приложения (драйверы), реагирующие на команды в реальном
времени. Команды передаются в обычном для DaqScript
стиле @command arguments ….
Для использования библиотеки нужно породить от класса DaqApplication свой (дочерний) класс, например, DemoDaqApplication. В этом классе “перекрываются” (override) некоторые методы, чтобы наполнить их своим содержанием, а также определяются и затем регистрируются обработчики требуемых для прикладной задачи команд.
import os, sys, time # <= импорт стандартных библиотек
from pycrwkit import * # <= импорт библиотеки pycrwkit
##########################################################
# Override DaqApplication class for Demo User Application:
##########################################################
class DemoDaqApplication(DaqApplication):
###############################
# Override Greetings on startup
###############################
def Greetengs(self):
super().Greetengs() # call inherited
print("Type '@help' to print help.")
####################################
# Override Processing of StdIn lines
####################################
def StdInProcessing(self,line):
if not isinstance(line,str):
return False
print("Input: ",line)
if (line == "exit"):
self.Terminate("Terminated.")
return super().StdInProcessing(line)
##################################
# Override HandleCommand for StdIn
##################################
def HandleCommand(self,cmd,arg):
if not isinstance(cmd,str):
return False
print("Command: ",cmd," ",arg)
# call inherited command handler
return super().HandleCommand(cmd,arg)
##############################
# Execute user polling actions
##############################
def ExecPollingActions(self):
return super().ExecPollingActions()
####################################
# Override handler for command @exit
####################################
def DoExit(self,cmd,arg):
code = StrToIntDef(arg,0)
self.Terminate("Terminated %d." % code,code)
return True
######################################
# Define new handler for command @test
######################################
def DoTest(self,cmd,arg):
n = StrToIntDef(arg,0)
print("Test %d requested." % (n))
return True
##########################################
# Create the DaqApplication object to run:
##########################################
Application = DemoDaqApplication("demo",4)
###########################################
# Then add new application command handlers
###########################################
Application.AddCommandHandler(Application.DoTest,"@test n - run test number n (demo)")
###################
# Main program body
###################
def execute_main():
Application.Welcome()
Application.RunLoop()
Application.Goodbye()
Application.SysExit()
######
# MAIN
######
if __name__ == '__main__':
execute_main()В данном примере определена и зарегистрирована (дополнительная)
команда @test и её обработчик
DoTest(). А также “перекрываются” методы:
Дополнительные команды регистрируются вызовом
Application.AddCommandHandler(f,s), где
f - функция обработчика команды, например
Application.DoTest(cmd,arg). Она должна
быть функцией класса и обрабытывать команду cmd с
аргументами arg. Строка s задает имя и
описание регистрируемой команды в виде
@cmd args - description, где @cmd - имя команды,
args - аргументы, description -
описание функции для команлы @help.
При работе объект DaqApplication выделяет из строки имя команды и находит в своем словаре зарегистрированную функцию обработки команды, а затем вызывает её для обработки этой команды.
В общем, всё готово для создания серверных программ для DAQ-системы на языке Питон.
Для написания клиента/сервера opcua нужно, помимо самой библиотеки opcua, иметь средства конфигурирования (чтения ini файлов) и асинхронного ввода-вывода (который нужен для обработки консольных команд, поступающих от клиентской программы DaqPascal).
Поэтому была собрана библиотека модулей python для создания клиента/сервера opcua:
На первый взгляд сейчас всё готово для начала кодирования клиента/сервера opcua с рабочим названием opcuasrv по аналогии с другими серверами crwdaq.
В репозиторий добавлен пакет daqgroup-opcua с инсталлятором install-daqgroup-opcua.run. Пакет нужен для поддержки сетевой технологии OPC UA. Он содержит библиотеки на Python, C/C++, а также документацию по OPC UA.
Этот пакет включает в себя:
Загрузчик и инсталлятор нужны для автономной установки в режиме offline, т.е. без доступа к сети Internet. Для автономной установки нужные пакеты загружаются (в реежиме online), переносятся на целевую машину и устанавливаются в режиме offline из этих загруженных пакетов. Загрузчик позволяет загружать пакеты вместе с зависимостями. Инсталлятор позволяет установить загруженные пакеты на целевой машине.
При установке пакет создает виртуальную среду Python в каталоге /opt/daqgroup/share/pyvenv. Виртуальная среда Python - каталог с пользовательскими настройками и пакетами, позволяющий запускать сценарии Питона локально, не затрагивая системную инсталляцию Питона. Это требуется для обеспечения безопасности системы.
В сценарии crwdep (crw dependencies) добавлены пакеты python3-pip, python3-venv, python3-confget, confget, нужные для работы daqgroup-asyncua.
В пакет crwkit добавлена команда
unix pyvenv для запуска команд в
виртуальной среде python.
unix pyvenv -p # печатает путь каталога виртуальной среды /opt/daqgroup/share/pyvenv
unix pyvenv python # запускает консоль Питона с настройками виртуальной среды
unix pyvenv pip list # список пакетов Питона в виртуальной среде
unix pyvenv script.py # запуск программы (сценария) Питон в виртуальной средеКоманда облегчает запуск программ python с нужными нам пользовательскими настройками и пакетами, независимо от настроек системы.
В команду @view list … добавлен фильтр
для поиска по ключевому слову:
@view list # список всех элементов (TControl)
@view -f list # список всех окон-форм (TForm)
@view list daq # список всех элементов по ключевому слову daq
@view -f list daq # список всех окон-форм по ключевому слову daqВведение ключевого слова связано с тем, что список получается
длинный, трудно найти нужное.
Ключевое слово облегчает поиск.
Добавлены команды:
@view handle n - ищет и возвращает
номер Handle элемента n, либо ноль
(если не найден).
Результат можно использовать, например, для проверки существования
элемента n.
Фактически это результат вызова
TWinControl.Handle.
@view wmwnd n - ищет и возвращает
номер WmWnd окна-формы n, либо ноль
(если не найден).
В общем случае значение wmwnd отличается от значения
Handle.
Фактически это результат вызова
TMasterForm.WmWnd.
Номер WmWnd используется для идентификации окон в
Оконном Менеджере (WindowManager).
Поэтому номер WmWnd можно использовать, например, в
вызовах команды wmquery.
Вызовы @view handle n,
@view wmwnd n можно использовать для
поиска элементов и окон-форм, проверки их существования, а также
манипуляции с окнами с помощью команды wmquery, которая
работает с номерами (идентификаторами) окон WmWnd.
Изменено поведение @view -t ….
Первоначально поиск шел только по имени, а с ключем
–title - только по загловку окна. Теперь поиск (по
умолчанию) всегда идет по имени или заголовку, но порядок поиска
меняется - с опцией -t поиск идет сначала по заголовку,
потом по имени.
Для эксклюзивного поиска только по имени или только по заголовку
добавлена опция -x или –xor.
То есть:
@view handle WINDOW # поиск окна по имени или заголовку
@view -x handle WINDOW # поиск окна только по имени
@view -x -t handle WINDOW # поиск окна только по заголовкуЗамечание по поводу опции @view -f …. С
опцией –forms поиск идет только по формам (наследникам
TForm). Поэтому при работе с формами (когда другие
элементы не нужны) есть смысл использовать эту опцию. Это существенно
сокращает объем вычислений и время поиска.
В команде @view params … серьезные
доработки. Покажем их на примере.
# вызов команды
@view -e -t params "Главная Консоль" [Action.GoHome] # задает параметры окна из секции
[Action.GoHome] ; # секция описания расположения окна
@set Form.Left 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom # с привязкой к Главному Окну
@set Form.Top 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom # с привязкой к Главному Окну
@set Form.Width -167 relative "$CRW_DAQ_SYS_TITLE" StatusBar.Absolute # ширина Главного Окна - 167
@set Form.Height 350
[]
# Примеры задания координат
@set Form.Left 0 relative "Window" Control.Right # задать X относительно правого края элемента Control из окна Window
@set Form.Top 0 relative "Window" Control.Bottom # задать Y относительно нижнего края элемента Control из окна Window
@set Form.Left 0 relative "Window" Control.Center # задать X относительно середины элемента Control из окна Window
@set Form.Top 0 relative "Window" Control.Middle # задать Y относительно середины элемента Control из окна Window
@set Form.Width 75 relative Screen # задать ширину == 75 процентов от ширины экрана
@set Form.Width 75 relative WorkArea # задать ширину == 75 процентов от ширины рабочей области экрана
@set Form.Width -75 relative Screen .Absolute # задать ширину на 75 пикселей меньше ширины экрана
@set Form.Width 75 relative "Window" Control.Absolute # задать ширину == 75 процентов от ширины Window/Control
@set Form.Width -75 relative "Window" Control.Absolute # задать ширину на 75 пикселей меньше ширины Window/ControlСобственно, к тому что было добавилась возможность задания точки отсчета координат с помощью псевдо-“расширения” имени элемента (Control) в окне (Window):
Кроме того, к специальным именам Screen (экран), Desktop (совокупный рабочий стол) добавилось имя WorkArea - рабочая область экрана. Под рабочей областью понимается область экрана без панели задач, меню и области уведомлений. Это то место, где могут располагаться обычные окна без “обрезания” по краям.
Эти новые возможности позволяют “приклеивать” окна к различным частям экрана или к другим окнам, подстраивая их размер.
Новые возможности использованы для задания координат основных окон пакета: Главного окна, Главной Консоли и окна DAQ-СИСТЕМА.
Это делается так:
# Задание действий (Action) по кнопкам "Домой" (GoHome)
# для Главного Окна (FormCrwDaq), Главной Консоли (FormConsoleWindow) и окна DAQ-СИСТЕМА (FormDaqControlDialog)
[System:Unix]
Action:FormCrwDaq.GoHome = @view -e params FormCrwDaq [Action:FormCrwDaq.GoHome]
Action:FormConsoleWindow.GoHome = @view -e params FormConsoleWindow [Action:FormConsoleWindow.GoHome]
Action:FormDaqControlDialog.GoHome = @view -e params FormDaqControlDialog [Action:FormDaqControlDialog.GoHome]
[]
# Секция описывает Действие: задание координат Главного Окна
# Привязка делается относительно Рабочей Области экрана (текущий вариант)
[Action:FormCrwDaq.GoHome+]
@set Form.Left 0 relative WorkArea .LeftTop
@set Form.Top 0 relative WorkArea .LeftTop
@set Form.Width -20 relative WorkArea .Absolute
@set Form.Height 55
[]
# Секция описывает Действие: задание координат Главного Окна
# Привязка делается в абсолютных координатах экрана (запасной вариант)
[Fallback:Action:FormCrwDaq.GoHome]
@set Form.Left 0
@set Form.Top 0
@set Form.Width 1200
@set Form.Height 55
[]
# Секция описывает Действие: задание координат Главной Консоли
# Привязка делается относительно элемента StatusBar Главного Окна
[Action:FormConsoleWindow.GoHome]
@set Form.Left 167 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom
@set Form.Top 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom
@set Form.Width -167 relative "$CRW_DAQ_SYS_TITLE" StatusBar.Absolute
@set Form.Height 350
[]
# Секция описывает Действие: задание координат окна DAQ-СИСТЕМА
# Привязка делается относительно элемента StatusBar Главного Окна
[Action:FormDaqControlDialog.GoHome]
@set Form.Left 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom
@set Form.Top 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar.LeftBottom
[]Таким образом, координаты Главного окна задаются относительно (рабочей области) экрана, а окна Главная Консоль и DAQ-СИСТЕМА “приклеиваются” к нему снизу.
Имейте в виду, поскольку DaqPascal использует тот же механизм описания расположения окон, новые возможности (задание точки привязки) можно использовать и в прикладных программах, позволяя выстраивать окна как вам требуется - например, “приклеивая” одни окна к другим.
В функции IsLexeme добавились лексемы:
Лексемы полезны для анализа строк с кавычками.
Серьезно доработана команда
@view ….
В ней появилось две дополнительные опции:
-f или –forms для применения
операций только к формам, а не ко всем элементам.
Эта опция позволяет сократить объем ненужной информации, если вам нужны
только окна-формы.
-t или –title для обращения к
окну по заготовку title, а не (внутреннему)
поимени,
Обращение по заголовку может быть полезным, т.к. внутреннее имя не
очевидно и часто неизвестно.
-e или –expand для подстановки
(расширения) переменных окружения типа $PATH.
Эта опция была сделана ранее, приведена здесь для справки.
Например:
@view list # показать список всех элементов
@view -f list # показать список всех окон-форм
@view min FormConsoleWindow # свернуть окно Главная Консоль (по имени)
@view -t min "Главная Консоль" # свернуть окно Главная Консоль (по заголовку)Кроме того, добавлена функция
@view params ….
@view -t params "Главная Консоль" @set Form.Left 200 # задает координату X
@view -t params "Главная Консоль" @set Form.Top 100 # задает координату Y
@view -t params "Главная Консоль" @set Form.Width 800 # задает ширину
@view -t params "Главная Консоль" @set Form.Height 350 # задает высоту
@view -e -t params "Главная Консоль" crwdaq.ini [Action.GoHome] # задает параметры из секции (из файла по имени ...)
@view -e -t params "Главная Консоль" [Action.GoHome] # задает параметры из секции (из файла по умолчанию)
# секция с описанием параметров
[Action.GoHome]
@set Form.Left 0 relative "$CRW_DAQ_SYS_TITLE" StatusBar # с привязкой к Главному Окну
@set Form.Top 20 relative "$CRW_DAQ_SYS_TITLE" StatusBar # с привязкой к Главному Окну
@set Form.Width 800
@set Form.Height 350
[]Новая функциональность служит для “продвинутого” задания координат окон на экране и позволяет
В Linux есть ряд команд для поиска (исполняемых)
файлов и команд. Например, команда which ищет файлы в
списке каталогов из переменной окружения PATH. Однако
многие команды (например, ifconfig) не входят в этот
список, так что which их не находит. Для расширенного
поиска файлов есть команда whereis, которая ищет файлы
в PATH, а также в списке известных системе каталогов
расположения служебных команд. Список этих каталогов можно узнать
вызовом whereis -l. Найти команду в
расширенном списке каталогов можно вызовом типа
whereis -b ifconfig, однако для извлечения
искомой команды требуется дополнительная обработка вывода. Кроме того,
для поиска системных динамических библиотек типа
lib*.so есть программа
ldconfig. Кэшированный список всех известных системе
библиотек (а это более 2000 библиотек) можно узнать
вызовом /usr/sbin/ldconfig -p. Нужную
библиотеку надо еще суметь найти в списке и выделить из него. К тому же
пакет crwkit имеет команду-оболочку
crwkit = crwrun =
unix, которая модифицирует переменную окружения
PATH для включения в поиск команд пакета
crwkit, так что вызов
unix which … имеет расширенные возможности
по сравнению с вызовом which … - он
находит не только системные команды, но и команды
crwkit.
Таким образом, для поиска бинарных (исполняемых) файлов есть несколько команд. При этом команды имеют различный формат вывода, из которого нужную информацию надо еще суметь извлечь.
Для упрощения работы была сделана “интегральная” утилита
unix whichis …, которая объединяет
возможности всех перечисленныех программ поиска команд и библиотек, к
тому же давая возможность запуска найденной команды с заданными
аргументами. Утилита whichis работает как программа
which (выдает путь искомой команды), но кроме поиска в
PATH также ищет в каталогах программы
whereis, а также умеет находить библиотеки
lib*.so с помощью программы
ldconfig.
Кроме того, команда whereis имеет опцию
-e или
--exec для запуска найденной команды.
Также была сделана программа
unix wanted …, которая является
расширением whichis, добавляя к поиску некоторые
каталоги crwkit - например, dimsite -
каталог DIM, smisite - каталог
SMI.
# стандартные средства Linux:
which foo # ищет команду foo в PATH
whereis -b foo # ищет команду foo в PATH и других системных каталогах
/usr/sbin/ldconfig -p # показывает список всех динамических библиотек lib*.so
# дополнительные средства crwkit
unix which foo # ищет команду foo в PATH и каталогах пакета crwkit
unix whereis -b foo # ищет в PATH, системных каталогах и каталогах crwkit
# вывод команды требует дополнительной обработки
# новые интегральные команды
unix whichis foo # ищет в PATH, системных каталогах и каталогах crwkit
unix whichis -e foo # ищет команду в (перечисленном), а затем запускает её
unix whichis libdim.so # ищет динамическую библиотеку (используя ldconfig)
unix wanted foo # работает как unix whichis foo
unix wanted dimsite # печатает расположение каталога DIM
unix wanted smisite # печатает расположение каталога SMI
# что получается в результате
which ls # печатает: /usr/bin/ls
which lscom # не работает, т.к. программа не в PATH (из пакета crwkit)
which ifconfig # не работает, т.к. программа не в PATH (в каталоге /usr/sbin)
whereis -b ifconfig # печатает: ifconfig: /usr/sbin/ifconfig (вывод требует обработки)
unix whichis ls # печатает: /usr/bin/ls
unix whichis lscom # печатает: /opt/crwkit/add/bin/lscom
unix whichis ifconfig # печатает: /usr/sbin/ifconfig
unix whichis -e ifconfig # запускает /usr/sbin/ifconfig
unix whichis libdim.so # печатает: /opt/dim/libdim.soТаким образом, команда unix whichis …
объединяет возможности which, whereis
и ldconfig, имея при этом максимально простой формат
вызова. А команда unix wanted … дублирует
возможности whichis, добывляя к ним поиск специфических
файлов и каталогов crwkit.
Команды unix whichis … и
unix wanted … могут применяться как
универсальное средство для поиска и запуска программ в сценариях, а
также (через механизмы task_run) в программах
DaqPascal.
Добавлен модуль _crw_pscap.pas для поддержки функций capabilities - так в Linux называют функции мандатного доступа.
Мандаты (capabilities) - это права (полномочия, возможности, разрешения) (обычного) процесса на выполнение опреленных привилегированных операций. У суперпользователя (root) есть мандаты на все операции. Остальным пользователям мандаты нужно специально выделять.
У мандатов есть номер (в настоящее время в диапазоне 0-40) и (документированное) имя. Например, мандат CAP_SYS_NICE=23 дает процессу право повышать приоритеты процессов NICE. Процесс обладает несколькими наборами мандатов - списками полномочий, которые делятся на наследуемые inherited, эффективные effective, доступные permitted, возможные boundary, внешние ambient, которые кратко обозначаются букмами i,e,p,b,a. Возможные мандаты - это мандаты, которые вообще в принципе возможны на данной системе. Эффективные мандаты - это текущие права процесса, которые ограничены доступными мандатами. При этом часть доступных мандатов может в данный момент не использоваться процессом. Процесс может менять набор эффективных мандатов, но только в рамках доступных. Наследуемые мандаты - это мандаты, которые могут наследовать дочерние процессы. Процесс может иметь мандат, но не передавать его дочерним процессам.
Наборы мандатов задаются в виде битовых масок QWord,
где каждый бит соответствует мандату с номером бита. Наборы мандатов
процесса номер PID можно прочитать в файле
/proc/PID/status в полях с именами
CapInh,CapEff,CapPrm,CapBnd,CapAmb, см. proc.
Поскольку работать с числами не очень удобно, наборы мандатов
представляются также в виде строк описания, состоящие из списков
мандатов и обозначений наборов. Например, описание
cap_net_bind_service,cap_sys_nice=ep
означает, что процесс имеет эффективный (e) и доступный
(p) список мандатов
(cap_net_bind_service,cap_sys_nice).
В модуле _crw_pscap.pas определен объект PsCap (от process capabilities), который содержит функции поддержки мандатов. Также в нем определены константы - идентификаторы мандатов. Например, вызов pscap.pid_has_cap(pid,CAP_SYS_NICE) проверяет наличие мандата CAP_SYS_NICE у процесса номер pid.
Функции поддержки мандатов реализованы не в полном объеме, а лишь в необходимом минимуме. Мочно читать и проверять наличие мандатов, чтобы узнать права процессов на выполнение операций. Задание мандатов (пока) не реализовано (хотя это не сложно), т.к. в этом (еще) нет необходимости. Мандаты обычно раздает администратор в “ручном” режиме, либо это делает инсталляционный сценарий.
Мандатный доступ является альтернативой использованию sudo. Если процессу нужно выполнять какой-то набор привилегированных операций (например, поднимать свой приоритет NICE или связываться по протоколу TCP с портами в диапазоне 1-1023), то не обязательно выполнять его под пользователем root, можно разрешить выполнение этих операций, предоставив мандат (разрешение).
Обычным способом предоставления мандатного доступа является задание мандатов выполняемого файла с помощью команды setcap.
В настоящее время пакету crwdaq при инсталляции (а также корректируется при запуске) задаются права
cap_net_bind_service,cap_sys_nice=ep # эффективные и доступные права bind и niceЭто значит, что исполняемому файлу crwdaq дается
эффективный и допустимый набор мандатов
cap_net_bind_service (разрешение на
подключение к портам TCP[1-1023]) и
cap_sys_nice (разрешение менять приоритеты
nice). По мере необходимости будут добавляться другие
мандаты.
В команду @sysinfo добавлен вывод
мандатов исполяемого файла EXE Caps и
текущего процесса PID Caps. Команда
@sysinfo со временем стала весьма
информативной и дает краткую сводку данных о системе с полезными для
практики сведениями. Теперь там можно узнать и список мандатов
процесса.
Переведена на новую версию crwdaq конфигурация demo_apc с драйверами источника питания APC.
В модуле _crw_ee.pas увеличено
значение максимальной длины выражений со старой величины
255 до новой величины
ee_MaxToksLen = 4095, т.е. примерно в
16 раз.
Необходимость увеличения длины выражений связана с тем, что при выполнении длинных команд в Главной Консоли иногда происходило “обрезание” команд и вследствие этого - их неисполнение. Теперь этого не должно происходить. Конечно, командный буфер остается конечным, но допустимая длина команд (около 4 КБ) пока представляется вполне приемлемой для практики. Не будет хватать - увеличим еще.
В новой версии проблема “урезания” длинных строк (и вследствие этого невыполнение команд) должна исчезнуть. Это наиболее актуально для команд типа @run, @log, @tooltip, @integrity, @event, @note и ряда других команд, часто формируемых программно и могущих содержать достаточно длинные выражения.
Также произведена массовая замена выражений типа
StrPLCopy(Buf,Str,SizeOf(Buf)-1) на
выражения типа StrCopyBuff(Buf,Str). Это
делает код более простым и понятным, а также исключает ошибки типа
неверного указания размера буфера. Код работает за счет использования
типизации, т.е. размер буфера определяется его типом.
Краткость и ясность кода достигается за счет перегрузки
функций (overload). Функции
StrCopyBuff(…) являются перегруженными,
т.е. для каждого типа буфера задается своя (одноименная) функция. Код
таких функций одинаков, отличается только тип аргумента.
Например:
function StrCopyBuff(var Buff:TParsingBuffer; const S:LongString):PChar; overload;
begin
Result:=StrPLCopy(Buff,S,SizeOf(Buff)-1);
end;Перегрузка функций позволяет легко и изящно решить вопрос копирования
строк в буферы разных типов,
одновременно автоматически обеспечивая их корректную обработку (т.е.
правильные размеры буфера).
Хорошее решение.
Обновлен пакет daqgroup-dunst. В конфигурации небольшие изменения, чтобы открывались ссылки по щелчку средней кнопкой мыши.
Задано такое поведение в dunstrc:
# по щелчку кнопкой мыши:
mouse_left_click = close_current # левой - закрыть текущее сообщение
mouse_middle_click = open_url, do_action, close_current # средней - открыть ссылку, закрыть сообщение
mouse_right_click = close_all # правой - закрыть все сообщенияЗавершена работа над утилитой wmquerygui.
Еще один неплохой инструмент в копилочку.
Доработана утилита crwdaq.utils.lm9 - интегральная утилита для вызова других утилит. В список утилит добавлены новые команды pingwin и wmquerygui, а также справки по DieselPascal и Lazarus.
Утилита wmquerygui доработана до вполне работоспособного состояния. Теперь она умеет делать почти все нужные операции над окнами - активизировать, прятать, показывать, отображать в различных режимах, закрывать (убивать), перемещать, менять размер.
Также реализован простейший поиск проблем, который позволяет найти окна, “улетевшие” за границы экрана.
Утилита wmquerygui станет хорошим дополнением к общему набору инструментов crwkit.
В команде @pid добавлены опции
@pid self # вернуть PID текущего процесса
@pid current # вернуть PID текущего процесса
@pid parent # вернуть PID родительского процесса
@pid prio tabs # напечатать используемые таблицы приоритетов процессов/потоковКоманда @pid prio tabs печатает таблицы
приоритетов, которые используются для пересчета логических приоритетов
процесса/потока в приоритеты операционной системы. Подробнее см.
тут.
Проведена доработка команды
@polling PriorityClass … и введен
связанный с ней параметр
crwdaq.ini [System:Unix] UseWindowsPriorityClass = 1.
Этот параметр задает поведение приоритетов потоков в
Unix по принципу “как в Windows”.
Проблема с заданием приоритетов Unix состоит в том, что в Unix приоритет потоков задается автономно, независимо для каждого потока. Приоритетом самого процесса принято считать приоритет его основного потока. При этом изменение приоритета процесса (т.е. его основного потока) не влияет на приоритеты других потоков. Другими словами, в Unix отсутствует понятие класса приоритета процесса, который есть в Windows. Напомним, в Windows процесс имеет класс приоритета, при изменении которого автоматически меняются приоритеты всех потоков процесса, а не только главного потока.
Параметр UseWindowsPriorityClass=1
разрешает эмуляцию класса приоритета процессов под
Unix, при этом эмулируется поведение, похожее на
Windows. То есть при изменении класса приоритета
процесса командой @polling PriorityClass …
меняется приоритет основного потока, а затем (по возможности) всех
остальных потоков опроса TPolling. Изменение
выполняется с помощью таблицы
приоритетов. Таким образом, система приоритетов под
Unix эмулирует систему, принятую под
Windows.
Заметим, что эта эмуляция работает только при штатном изменении приоритета средствами пакета crwdaq. Если изменить приоритет процесса “извне” (например, через “Системный Монитор”), то поведение будет прежним, как принято в Unix.
Напомним, что команда
@polling PriorityClass … может работать в
режиме монитора.
Например, при вызове
@polling PriorityClass High 5000
исполнительная система пакета crwdaq будет каждые
5 секунд проверять и при необходимости корректировать
класс приоритета. При этом любое внешнее воздействие будет иметь лишь
кратковременный эффект.
Сделанные доработки закрывают (в первом приближении) работу над системой приоритетов в crwdaq.
В ходе работы столкнулся со следующей проблемой:
Проблема оказалась до смешного простой - окно каким-то образом “улетело” за пределы экрана. То есть программа запущена и работает нормально, просто отображается … за пределами экрана. Хуже всего, что перезапуск программы не помогает - она помнит свои координаты и при перезапуске опять “улетает” за пределы экрана.
Это и есть проблема “потерянных” окон.
Указанную проблему удалось решить с помощью консольной утилиты
unix wmquery …, хотя вызов утилиты не
сказать что совсем простой. Пришлось немного повозиться с аргументами
вызова.
Чтобы в будущем облегчить процесс работы с окнами Рабочего
Стола (включая обнаружение, идентификацию, завершение,
изменение положения и размеров), была сделана графическая утилита
unix wmquerygui. Утилита wmquerygui.lm9 написана на
DieselPascal. Фактически это графическая оболочка для
unix wmquery.
Утилита wmquerygui позволит удобно работать с окнами Рабочего Стола, и в частности, находить и возвращать на экран “потерянные окна”, случайно оказавшиеся за пределами экрана.
Заведен параметр
crw32.ini [System:Unix] WM_GRAVITY_DEFAULT = 0.
Параметр Gravity (гравитация) задает способ привязки
при задании координат окон в Gtk.
Спецификация XDG
описывает возможные способы привязки в разделе Window
Geometry.
Параметр гравитации используется при задании координат в
wmquery, например:
# Задать координаты окна с номером 0x05C00007
# Параметры геометрии: Gravity=0, Left=200, Top=100
unix wmquery moveresizewindow -wnd 0x05C00007 -geom 0,200,100Параметр Gravity принимает значение 0..10:
Пока что алгоритм работы “гравитации” не совсем ясен. Проблема в том, что в расчете точки привязки учитывается “декорация” Менеджера Окон. Это, вероятно, заголовок окна, возможно его рамки. Этот вопрос нужно выяснять. Пока достаточно того, что значение гравитации “по умолчанию” можно менять на уровне программы.
Пока для гравитации принято значение по умолчанию 0, дальше будем разбираться.
Пакет daqgroup-diesel с интерпретатором DieselPascal оставался у нас последним, который еще не переведен под ALSE. Хотя он вроде бы работал в сборке под ALCE, это всё-таки не “родная” сборка под ALSE. К тому же сами коды Дизель не обновлялись уже несколько лет и довольно сильно “отстали” от официальной версии автора.
Поэтому была сделана сборка DieselPascal под ALSE на fpc-3.2.2+Lazarus-3.6.0, а заодно его обновление с версии 2.1.6 до 2.3.5. Кроме того, в сборку добавлено зеркало домашнего сайта DieselPascal с оригинальной версией, что может оказаться полезным (наша версия по ряду причин немножко поправлена).
Процесс компиляции проходил непросто (пришлось повозиться с установкой и настройкой пакетов), но по результату всё получилось хорошо. Во всяком случае, начальное тестирование не выявило проблем с DieselPascal.
На этот раз сборка пакетов и самого DieselPascal проводилась не во временной “песочнице”, а в каталоге fpcdeluxe/ccr, где штатно располагаются дополнительные пакеты lazarus. Для сборки DieselPascal надо доустановить 8 пакетов: fpspreadsheet, ibx, lazreport, synapse40, tachart, TxDBF, VisualTech, ZEOSDBO. Кроме того, пришлось повозиться с путями поска в параметрах проектов.
Теперь все пакеты в репозитории daqgroup актуальны под ALSE.
Программа fpcupdeluxe кроме стандартной установки fpc+lazarus содержит список из более 100 дополнительных пакетов, которые можно скачать и установить по желанию. Эти пакеты скачиваются по ссылкам, содержащимся в файле fpcup.ini. Поскольку в offline режиме скачивание недоступно, было решено закачать репозиторий по ссылкам в каталог downloads-fpcup, чтобы эти файлы были в репозитории daqgroup. Это к тому же снимает необходимость делать отдельную сборку fpcupdeluxe-max с дополнительными пакетами. Вместо этого разработчикам предлагается ставить сборку fpcupdeluxe-min с минимальной версией fpcupdeluxe, а дополнительные пакеты доустанавливать у себя самостоятельно, взяв их из каталога downloads-fpcup. А сборка fpcupdeluxe-max теперь используется для других целей.
Изменилась концепция сборки fpcupdeluxe-max. Если раньше это была сборка fpcupdeluxe-min с дополнительными пакетами, выбранными, в общем, случайно и реально зачастую ненужными, то теперь fpcupdeluxe-max фактически будет сборкой для DieselPascal. То есть в этой сборке будут установлены пакеты, нужные для компиляции DieselPascal, а также сами коды DieselPascal в каталоге fpcupdeluxe/ccr. Это разумно, т.к. DieselPascal реально используется и готовую сборку для его компиляции иметь хочется. А другие библиотечные пакеты, если они нужны, ставятся отдельно теми, кому они нужны. Нет необходимости делать для этого отдельную сборку fpcupdeluxe.
К слову сказать, пакет crwdaq компилируется на версии fpcupdeluxe-min, так что для него не нужна сборка fpcupdeluxe-max. А вот для компиляции DieselPascal своя сборка не помешает, т.к. с установкой дополнительных пакетов много возни, которую не хотелось бы каждый раз делать с нуля.
Таким образом, теперь fpcupdeluxe-min - минимальная сборка FPC+Lazarus, а fpcupdeluxe-max - сборка для компиляции DieselPascal.
В crwkit добавлена утилита
unix pingwin - команда
ping в графической оболочке
DieselPascal. Также добавлен файл
resource\shell\pingwin.lm9 и вызов этой
команды в crwdaq/Ссылки/DAQ-система.
Утилита служит для удобства использования команды ping.
В консольных окнах TFormConsoleWindow введен ChecкBox и кнопка для разрешения/запрета консольного ввода, т.е. поля ввода команд в консоль. Это сделано для того, чтобы избежать случайного ввода “мусора” в консоль. Ведь вообще-то консоль - это скорее отладочное средство, которое конечным пользователям не очень-то и нужно. Чтобы пользователи случайно чего-нибудь вредного не навводили, консоль можно запретить.
Параметр
crwdaq.ini [System] ConsoleAutoEnableInput = 0
управляет начальным значением флага разрешения консольного ввода.
Сейчас, при значении 0, консольный ввод запрещен по
умолчанию. Для разрешения ввода в консоль надо нажать кнопочку с
ключиком слева от поля консольного ввода. Кнопочка сработает только при
уровне доступа User и выше. То есть при гостевом уровне
доступа консоль будет заблокирована.
Сделаны сборки fpcupdeluxe под AstraLinux и Win32.
Сборка под AstraLinux была сделана потому что сделанный ранее однооконный режим IDE не понравился. В новой сборке вернулись к SDI интерфейсу. А сборка fpc-3.2.2+Lazarus-3.6.0 под Win32 была сделана впервые.
Вроде всё работает. Хотя в версии для Gtk2 наблюдались подвисания IDE при попытке изменить размеры окна в редакторе свойств. При этом такой проблемы нет под Win32, а также при изменении размера/плоложения окна путем перетаскивания мышью.
Сделаны исправления в пакете daqgroup-dunst. Там исправлены мелкие ошибки в конфигурации dinst, из-за которых он не всегда отображал картинки (иконки) при выводе сообщений.
Сделаны исправления в пакете doublecmd-settings. Там отключены флаги Сворачивать в Область Уведомлений, т.к. со значками в Области Уведомлений возникают проблемы. Это какой-то баг оболочки Fly - картинки время от времени могут исчезать, а программа может не восстанавливаться из свернутого состояния.
В библиотеку crwlib добавлена функция GetListOfShells. Она служит для получения списка разрешенных/доступных/существующих программ-интерпретаторов оболочки, таких как bash, sh под Unix или cmd.exe, powershell.exe под Windows. Это дает возможности для анализа командных строк - типа, является ли программа интерпретатором оболочки.
Также добавлена строка Shells в список вывода
@SysInfo, в также в
ParamStr('System Os Shells').
В функции DebugOut снято ограничение на длину строк 255, которое было до этого. Кроме того, в функцию теперь можно передавать текст (многострочный).
В конфигурацию добавлен параметр
crwdaq.ini [System] ConsoleAutoFocusInput = 1.
Этот параметр включает опцию “автофокуса”
TFormConsoleWindow.FocusInputOnActivate в консольных
окнах. При автофокусировке поле ввода Input в
консольном окне автоматически получает фокус ввода при активизации окна.
Раньше для получения фокуса ввода нужно было явно кликнуть мышью в поле
Input, чтобы оно получило фокус. Практика покажет,
удобно ли эта функция автофокусировки ввода в консольных окнах. Если
будет неудобно, опцию всегда можно отключить.
По результатам работы еще два модуля очищены от маркера
SKIP_DRAFT для черновиков. То есть
имевшиеся в них (и отложенные на потом) проблемы решены и их код стал
условно “чистым”. Осталось порядка десяти модулей с маркером черновиков.
Постепенно почистим всё.
Стандартный для Windows способ чтения списка процессов PSAPI (Process Status API) обладает довольно высокой скоростью, но имеет недостаток - он не может считывать командную строку CommandLine процессов. По этой причине в Windows функция GetListOfProcesses имела ограниченную функциональность - она не могла возвращать CommandLine для списка процессов.
Для решения этой проблемы в библиотеку crwlib добавлен модуль поддержки WMI - _crw_wmic. Он используется только под Windows, т.к. под Unix используются другие методы. Модуль нужен для чтения списка процессов средствами WMI, включая CommandLine.
Официальным путем для чтения списка процессов с командной строкой CommandLine является использование WMI. Инструментарий WMI - Windows Management Instrumentation - это набор средств для управления компьютером, позволяющий получать огромное количество информации о системе - и в частности о процессах. Фактически WMI работает как база данных с языком запросов WQL (WMI Query Language), который фактически является одним из многочисленных диалектов языка SQL (у каждой крупной базы данных по факту свой диалект).
Использование WMI позволило модифицировать функцию
GetListOfProcesses так, что теперь она умеет выдавать
список процессов с командной строкой.
Например, команда @pid list теперь выдает
такой список.
Измерения показали, однако, что запрос WMI для получения списка процессов занимает около 40 мс (!!!), что является очень дорогой операцией. Для сравнения, чтение списка из 100 процессов средствами PSAPI занимает порядка 2.8 мс (порядка 28 мкс на один процесс). Таким образом, WMI работает примерно в 15 раз медленнее.
По этой причине функция GetListOfProcesses использует более быстрый PSAPI для получения списка процессов без CommandLine, а если при вызове указан флаг Detail (нужны детали), то используется WMI для получения списка процессов c указанием CommandLine.
Таким образом, теперь функция GetListOfProcesses под Windows обладает полной функциональностью, выдавая быстрый список без указания CommandLine при параметре Detail=false, либо выдает подробный список процессов с указанием CommandLine, если указать Detail=true. При этом, однако, затрачивается существенно больше времени.
К счастью, в большинстве программных алгоритмов не требуется чтение списка процессов с подробностями, что позволяет сохранять высокую скорость исполнения прикладного кода, использующего GetListOfProcesses. Список процессов с указанием CommandLine нужен в основном разработчикам для анализв работы системы. Высокая скорость при этом обычно не требуется.
В целом доработка функции GetListOfProcesses завершена для обеих платформ Unix и Windows.
Проведена оптимизация DebugOutText. Меньше памяти, выше скорость.
Поправлен вывод в журнал sound.log - он как раз использует DebugOutText.
Процедура GetListOfProcesses серьезно доработана (версия под Linux).
Решена проблема TASK_COMM_LEN. Эта
проблема состоит в том, что файлы /proc/pid/stat,
/proc/pid/status используют для имен задач (поле
comm) буфер размера
TASK_COMM_LEN = 16, определенный в ядре
Linux. Это значит, что имена задач длиннее
15 символов молча обрезаются. Как написано в
документации по /proc/pid/stat:
Strings longer than
TASK_COMM_LEN (16)characters (including the terminating null byte) are silently truncated..
В списке задач, тем не менее, есть имена длиннее 15 символов - это процессы ядра, на имена которых правило обрезания не распространяется.
Таким образом:
< 15 не
обрезаны, т.к. умещаются в буфер с запасом.> 15 не
обрезаны, т.к. это процессы ядра, которые могут иметь более длинные
имена.= 15 под вопросом,
т.к. они могут быть обрезаны (а могут и не быть).Для имен comm длиной 15 символов считывается /proc/pid/cmdline и делается попытка прочитать имя файла (без пути) из аргументов argv[0] или argv[1] (это на случай shell скрипта). Если имя файла длиннее значения comm и начинается с значения comm (то есть первые 15 символов совпадают), то в качестве имени задачи берется значение имени файла. Это в целом соответсвует соглашениям, которые использует большинство программ и библиотек.
Проведенная работа устраняет проблемы при работе с длинными именами
программ. Например, раньше команда
@pid kill crwdaqwatcher.sh не работала,
т.к. имя задачи crwdaqwatcher.sh обрезалось до
crwdaqwatcher.s, т.е. до 15 символов.
Сейчас эта команда работает корректно.
Поведением функции GetListOfProcesses управляют флаги:
glopf_Threads - включать в список
число потоков (обычно нет).glopf_CmdLine - включать в список
командную строку (работает дольше).glopf_FixName - исправлять обрезанные
имена задач comm (как описано выше).Таким образом вывод GetListOfProcesses имеет формат:
PID, PPID, PRIORITY, TASKNAME, [, THREADS] [, CMDLINE]Первые 4 поля PID,
PPID, PRIORITY,
TASKNAME присутствуют всегда, поля
THREADS и CMDLINE зависят от
флагов.
Кроме того, поле TASKNAME корректируется при указании
флага glopf_FixName.
Команда @pid list доработана - теперь
она может содержать параметр
@pid list 0/1/2/3 для указания режима
вывода списка.
Без параметра выдается максимальный список с табличным
форматированием.
В модуле общей памяти _crw_sharemem.pas сделано выравнивание, т.к. там тоже есть атомарный счетчик.
Сделан модуль _crw_procps.pas по
мотивам пакета procps, предоставляющего библиотеку
libprocps. Это библиотека для разбора файловой системы
/proc/. В модуле сделан разбор файла
/proc/pid/stat, что позволяет ускорить
работу функции GetListOfProcesses, которая
получает список работающих процессов. Поскольку это часто используемая,
базовая функция, её ускорение будет кстати. До сего времени список
файлов читался из нескольких файлов, включая
/proc/pid/status,
/proc/pid/sched,
/proc/pid/cmdline, что связано с большими
объемами чтения и парсинга (анализа текста). Сейчас большая часть
параметров читается из одного файла
/proc/pid/stat. На всякий случай старый
алгоритм можно вернуть указанием параметра
crwdaq.param.ini [System:Unix] prefer_proc_pid_stat = 0.
Было замечено, что команда @pid list в
Главной Консоли работала очень медленно (десятки
секунд). Это было связано с выполнением избыточного числа ненужных (в
данном контексте) вычислений.
После исправления команда выполняется (достаточно) быстро.
Была сделана команда измерения скорости
@testbench GetListOfProcesses [0/1].
Параметр [0/1] (по умолчанию
prefer_proc_pid_stat) задает алгоритм
(старый/новый=status/stat). Измерения показали, что вызов
GetListOfProcesses примерно пропорционален числу
опрашиваемых процессов и занимает:
| Параметр | Метод | Время вызова на один процесс, мкс |
|---|---|---|
| 0 | /proc/pid/status | 35 мкс |
| 1 | /proc/pid/stat | 21 мкс |
| - | Windows10 | 28 мкс |
Таким образом, проверка существования процесса GetListOfProcesses(pid,0,’’) займет около 21 мкс, а получение списка из 300 процессов GetListOfProcesses(0,0,’’) - примерно 6300 мкс = 6.3 мс. Это надо учитывать при программировании. Если надо проверить наличие процесса pid, лучше указать его в аргументе, а не искать в списке всех процессов.
Для примера указано время чтения списка процессов (в расчете на один процесс) для системы Windows10. Видно, что времена сопоставимы (под Linux получается немного быстрее).
Сделана сборка актуальной (стабильной) версии fpcupdeluxe. Авторы fpcupdeluxe считают стабильной на данный момент версию fpc-3.2.2+lazarus-3.6. Предыдущая версия была fpc-3.2.2+lazarus-2.2.6. То есть компилятор не изменился, а вот lazarus существенно обновился. Обновление сборки lazarus было предпринято в надежде, что разработчики поправят “глюки” в реализации визуальных элементов (виджетов) в gtk.
Пакет crwdaq и все прочие программы были пересобраны под fpc-3.2.2+lazarus-3.6. Проблем не возникло, компиляция прошла гладко.
При тестировании программы стало ясно, что команда lazarus действительно серьезно поработала над визуальными компонентами gtk. Во всяком случае, проблем с отрисовкой окон стало меньше, а сама отрисовка (по ощущениям) идет быстрее. При отключении “патча”, исправляющего “заморозку” отображения окон (из-за которого окна “мигали”) всё вроде бы работает нормально. То есть разработчики действительно исправили какие-то ошибки в виджетах gtk2. Это радует. Выходит, не зря повозился со сборкой новой версии lazarus.
Патч, исправляющий “заморозку” отображения окон, отключается
указанием параметра
crw32.params.ini [System] EnableSdiFormCodePills = 0.
Если потребуется, его можно включить снова.
Сборка под новой версией lazarus работает намного приятнее и “мягче”, т.к. рисует быстрее и гораздо меньше “миганий”.
Для проверки субъективного впечатления о скорости рисования были
сделаны измерения на конфигурации
demo_paint_bench, в которой измеряется
время отрисовки кнопки SimpleButton:
| Сборка | Время отрисовки кнопки, микросекунд |
|---|---|
| crw32-win32-delphi5 | 70 |
| crwdaq-win32-lazarus-2.2.6 | 25 |
| crwdaq-astra-lazarus-3.6 | 30 |
Как видно из таблицы, отрисовка идет более чем в 2 раза быстрее, чем под crw32, при этом скорость отрисовки под gtk лишь на 20% уступает скорости win32.
В общем, с рисованием теперь вроде бы всё хорошо.
Как уже было сказано ранее, в оболочке Fly под
ALSE на окна накладывается гранулярность (сетка), так
что задание координат окон (форм) Рабочего Стола идет
не совсем просто. Например, анализ отладочных логов показывает, что,
например, при задании координат окна командой
@WinDraw КОНСОЛЬ &TESTBENCH|Left=167|Top=317|Options=-Left,-Top
окно получает в реальности координаты (168,318) -
видимо, выравненные по модулю 2. Хуже того, поскольку
задание координат окна - сложная итерационная процедура, особенно с
учетом клиент-серверной организации системы X Windows,
то координаты окна меняются во времени, т.к. обработка изменений
координат идет через команды (события) и очередь сообщений. То есть мы
задаем Form.Left:=167;, а через какое-то время (с
задержкой) получаем Form.Left=168.
Что это означает для функции @WinDraw?
Это означает некоторые проблемы при выполнении фиксации координат типа
Options=-Left. Напомним, что у окон есть
текущие координаты на экране, а есть
фиксированные координаты, к которым окно
“привязывается”. Если текущие координаты отличаются от фиксированных,
система возвращает окна к фиксированным координатам. В старой реализации
при выполнении команды Options=-Left фиксировались
текущие (на момент исполнения) кординаты окна. А они, как отмечалось,
меняются во времени. Если команда Options=-Left
выполняется отдельно от задания координат Left=167, то
эти команды выполняются в разное время (в цикле обработки очереди
событий), а поэтому команда Options=-Left может
зафиксировать какое-то промежуточное (можно сказать, случайное) значение
Left. В результате окна выстраиваются неправильно (не в
тех координатах, которые были заданы).
Алгоритм обработки @WinDraw был
модифицирован. Сначала @WinDraw считывает из командной
строки все координаты
Left,Top,Width,Height
и запоминает их. Затем считываются и устанавливаются опции
Options, в частности, опции фиксации координат. После
обработки всей команды устанавливаются запомненные
ранее (заданные командой) текущие координаты окна, а также фиксированные
координаты. Это гарантирует, что фиксированные координаты будут точно
соответствовать заданным в команде.
Есть только одна тонкость. Этот алгоритм работает, если задание
координат и опция фиксации заданы в одной команде
Left=167|Options=-Left, а не разнесены в два вызова
@WinDraw. Разделение вызова на два
делалось потому, что получалась длинная, неудобная в работе командная
строка. Однако теперь необходимо задавать опцию
фиксации в той же команде, где задается координата. Если хочется
разделить команду (для читабельности) на две, то можно задать отдельно
другие опции типа +Close,-Max,+Min, но
координаты и их фиксацию надо делать
вместе, одной командой.
Например:
# ПРАВИЛЬНО
@WinDraw DIM_PING.MAIN.CTRL|Left=0|Top=0|Width=700|Height=800|Options=-Left,-Top,-Width,-Height
@WinDraw DIM_PING.MAIN.CTRL|Options=-Min,-Max,-Close,-HScroll,-VScroll,+StatusBar
# НЕПРАВИЛЬНО
@WinDraw DIM_PING.MAIN.CTRL|Left=0|Top=0|Width=700|Height=800|Options=-Min,-Max,-Close,-HScroll,-VScroll,+StatusBar
@WinDraw DIM_PING.MAIN.CTRL|Options=-Left,-Top,-Width,-HeightВ правильном варианте координаты и их фиксация заданы в одной
команде, а дополнительные опции - в другой.
В неправильном (ошибочном) варианте координаты и их фиксация заданы
разными командами. Так не надо.
Из-за изменений в новой версии pandoc программа markdownviewer стала выдавать документы без подсветки синтаксиса языков программирования. Пришлось скорректировать файл стилей CSS. Теперь markdownviewer работает правильно.
Сделана утилита daqgroup-mime для работы с файлом привязки типов MIME.
unix daqgroup-mime -c # печать (cat) файла привязки типов MIME от daqgroup
unix daqgroup-mime -p # путь (path) файла привязки типов MIME от daqgroup
unix daqgroup-mime -q # печать (query) файла привязки типов MIME ~/.mime.types
unix daqgroup-mime -s # установка (setup) файла привязки типов MIME ~/.mime.types
# т.е. файл привязки от daqgroup копируется в ~/.mime.typesФайл привязки типов MIME содержит привязку
расшинений имен файлов к типам MIME. Например, строка
text/plain txt ini cfg говорит, что файлы
с расширениями
txt,ini,cfg должны
интерпретироваться как простые текстовые файлы типа
text/plain.
Пакет crwkit хранит свою копию привязки типов
MIME.
Содержимое файла привязки можно узнать вызовом
unix daqgroup-mime -c.
Путь файла привязки можно узнать вызовом
unix daqgroup-mime -c.
Файл $HOME/.mime.types в домашнем
каталоге пользователя содержит текущие настройки привязки типов
MIME, используемые текущим пользователем для
определения типов файлов. Программы (например, Firefox)
используют этот файл настроек для определения того, каким образом
обрабатывать файлы (отображать/сохранять/запускать и т.д.).
Команда unix daqgroup-mime -s
устанавливает файл привязки типов MIME, т.е. копирует
определения daqgroup в файл профиля пользователя
$HOME/.mime.types.
Команда нужна для того, чтобы проверять/задавать файл привязки типов MIME для текущего пользователя - например, при инсталляции.
Иначе, если файл привязки в профиле пользователя не задан, возникают проблемы. Например, Firefox не будет отображать некоторые типы файлов, а вместо этого предложит их сохранять. То есть, например, посмотреть текст ini файла в браузере будет нельзя.
Поскольку функции LockedXXX были заменены на безопасные атомарные счетчики TAtomicCounter, а “простые” критические секции RTL - на безопасные объкты TSysCriticalSection, стало интересно сравнить их по производительности. Был написан небольшой тест, который дал следующие результаты:
# Benchmark AtomicCounters:
LockedInc/Dec(Counter) takes 1000 ms per 58252000 ops, performance 17.167 ns per op
AtomicInc/Dec(Counter) takes 1000 ms per 53405300 ops, performance 18.725 ns per op
Difference: 9.075 %
#Benchmark CriticalSections:
RtlEnter/Leave(CritSect) takes 1000 ms per 39478200 ops, performance 25.330 ns per op
SysEnter/Leave(CritSect) takes 1000 ms per 50402800 ops, performance 19.840 ns per op
Difference: 21.675 %В тестах измерялось время пар операций LockedInc/LockedDec, а также EnterCriticalSection/LeaveCriticalSection.
Как видно из тестов, для атомарных счетчиков “накладные расходы” составили менее 10%. Для критических секций реализация на объектах неожиданно оказалась на 20% быстрее. Причина не совсем ясна, но в любом случае это приемлемые результаты. Заодно получаем оценку (около 9ns) на вызов атомарной функции типа LockedInc. Это составляет около 30-40 циклов процессора (при частоте 2.4GHZ). На этом фоне отличие в 10% означает всего 3-4 цикла процессора, что является приемлемой ценой за безопасность счетчиков и критических секций.
К этому надо добавить, что счетчики и критические секции обычно занимают ничтожную часть времени выполнения. Поэтому замена реализации счетчиков и критических секций на новую вообще не окажет заметного влияния на производительность приложений.
Безопасные критические секции были выделены в модуль _crw_critsect. Как
и модуль _crw_atomic, он является скорее
внутренним, то есть обычно не используется в uses, так
как его основная интерфейсная часть вынесена в модуль
_crw_alloc. В модуле для атомарных
счетчиков и для критических секция реализована функциональность подсчета
ссылок, т.е. контроль создания/уничтожения объектов. Счетчики
записываются в файл leakage.log на выходе
из программы, что позволяет контролировать корректность кода.
Модуль _crw_alloc с помощью перегрузки
функций
(Init|Done|Leave|Enter)CriticalSection
предоставляет возможность работать с безопасными критическими секциями
как раньше, надо только заменить TRTLCriticalSection на
TSysCriticalSection и не забывать инициализировать их
значением nil.
В целом проблема с выравниванием адресов решена и более возникать не должна.
Была выполнена пересборка fpcupdeluxe под ALSE. Как и раньше, была сделана версия min и max. В версии max не удалось собрать pascalscada, но он был скачан в исходниках с github и помещен в каталог ccr. При необходимости можно попробовать собрать его вручную.
Сборка была сделана для fpc-3.2.2 и lazarus-2.2.6, как и ранее. Пока работаем с этой версией.
С использованием обновленной версии fpcupdeluxe был полностью пересобран пакет crwdaq со всеми вспомогательными программами и библиотеками. И это хорошо - при компиляции под старой версией fpcupdeluxe были предупреждения (warning) о проблемах с линковкой, которые теперь исчезли. Видимо, в старой версии fpcupdeluxe были зависимости от библиотек, которые в ALSE недоступны. Вроде бы всё собиралось и работало, но наличие предупреждений - нехороший знак, так что перекомпилировать стоило. В общем, теперь всё должно быть хорошо.
Таким образом, пакет crwdaq полностью перешел под ALSE.
Поскольку ранее возникла проблема выравнивания адресов (при использовании критических секций), было решено заняться также атомарными операциями со счетчиками (функции InterlockedXXX). Как пишет в документации Microsoft в описании функции InterlockedIncrement64:
The variable pointed to by the Addend parameter must be aligned on a 64-bit boundary; otherwise, this function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.
Это значит, что переменные счетчиков должны быть выравнены, иначе результат непредсказуем.
Чтобы сделать безопасные (имеющие гарантированно выравненные адреса)
счетчики, был сделан модуль _crw_atomic,
реализующий класс счетчика TAtomicCounter. Этот класс
гарантирует правильное выравнивание адреса счетчика и защищает его от
неправильного доступа (неправильно обращаться к счетчику без
блокировок). В модуле _crw_alloc сделаны
перегруженные функции LockedXXX, похожие
на старые функции работы со счетчиками, только с типом .
Для облегчения использования атомарных счетчиков с минимальными изменениями кода были перегружены функции LockedXXX, которые позволяют работать со счетчиками примерно как раньше:
var ac : TAtomicCounter;
...
LockedInit(ac); // Создание счетчика
LockedInc(ac); // Инкремент счетчика
n:=LockegGet(ac); // Чтение счетчика
LockedSet(ac,123); // Запись счетчика
LockedFree(ac); // Освобождение счетчикаИспользование перегруженных функций позволяет заменять обычные счетчики на атомарные с минимальными изменениями кода. Было изменено более 20 модулей, где счетчики простых типов (LongInt, Cardinal, Int64, QWord) заменялись на TAtomicCounter.
Если все сделано верно, то о проблеме выравнивания можно будет не беспокоиться. Достаточно использовать тип TAtomicCounter вместо простых счетчиков. При этом можно работать со счетчиками в прежнем стиле.
Единственным отличием является то, что счетчики TAtomicCounter надо инициализировать/завершать вызовом LockedInit/LockedFree, чтобы избежать утечки памяти.
При запуске под ALSE была обнаружена проблема с
фиксацией размеров окон (FixedBounds).
Проблема состояла в мигании зафиксированных окон, а также (иногда) в
неверном их расположении.
Напомним, что для упорядочивания графического интерфейса была (уже давно) сделана возможность фиксации расположения окна (левый/верх/ширина/высота=Left/Top/Width/Height). Периодически (раз в одну-две секунды) положение окон корректируется исполнительной системой. Если окно было сдвинуто, оно вернется на фиксированное место.
Анализ показал, что проблема заключается в гранулярности положения окон, которую вносит, по всей видимости, оконный менеджер Fly. Гранулярность означает, что окна “приклеиваются” к определенной координатной “сетке” с шагом порядка 8 пикселей (точное значение неизвестно). По этой причине при указании координаты окна получаются не точно те, которые заданы при вызове, а те, которые установит оконный менеджер. Обнаружив, что положение окна отличается от ожидаемого, исполнительная система повторяла команду задания положения окна, и так в цикле. Отсюда и мигание.
Для решения проблемы в исполнительной системе была введена своя гранулярность, т.е. окна, координаты которых не отличаются друг от друга в пределах “гранулы” (или ячейки), считаются идентичными и не меняют свое положение. Это работает, если шаг “сетки” оконного менеджера меньше или равен размеру гранулы плюс один. Например, гранулярность 7px справится с сеткой с шагом 8px (здесь px - пиксель).
Гранулярность задается в файле crwdaq.ini:
[System]
…
FixedBoundsTolerancePX = 7 ; Tolerance to compare FixedBounds pos X = Left
FixedBoundsTolerancePY = 7 ; Tolerance to compare FixedBounds pos Y = Top
FixedBoundsToleranceSX = 7 ; Tolerance to compare FixedBounds size X = Width
FixedBoundsToleranceSY = 7 ; Tolerance to compare FixedBounds size Y = Height
…В настоящее время принята гранулярность 7px, что соответствует сетке 8px. Гранулярность, возможно, зависит от настроек оконного менеджера, но где они лежат и регулируются ли они, пока неясно.
Гранулярность фиксации положения окон означает, что окно фиксируется с некоторой точностью. Небольшое (в пределах гранулы) смещение окна считается допустимым. Окно ставится “на место” только если переместить его за пределы текущей “гранулы”.
После введения гранулярности проблема “мигания” и неверного расположения зафиксированных окон вроде бы исчезла.
Обновлен пакет daqgroup-lcard. Теперь он зависит от пакетов lcomp-dkms, liblcomp1, liblcomp1-dev, поставляемых LCard. То есть их надо предварительно установить.
В новой версии драйверов используется механизм DKMS (Dynamic Kernel Module Support). В этой модели драйверы компилируются из исходников в процессе установки, что гарантирует актуальность (соответствие версии драйверов и ядра). Драйверы компилируются в каталог /var/lib/dkms/lcomp/.
Утилита unix ldev-cpl модифицирована с
учетом изменений в составе пакетов и расположении драйверов.
Всё остальное остается в силе.
С переводом daqgroup-lcard все пакеты, входящие в состав daqgroup, готовы под ALSE.
Теперь остается “почистить” код crwlib и
crwdaq, устранив обнаруженные проблемы.
Тогда можно считать переход под ALSE завершенным.
Проводилась правка сценариев инсталляции и запуска ROOT.
Проводилась правка сценариев инсталляции и запуска crwdaq.
В сценариях, в частности, проверяется приложение по умолчанию для
DieselPascal и ROOT. Если оно
неверное, оно восстанавливается. Это нужно, чтобы правильно открывались
файлы с расширениями .lm9 и
.root.
Правильная привязка:
| Расширение | Тип MIME | Приложение |
|---|---|---|
.lm9 |
application/x-diesel | CrossMachine.desktop |
.root |
application/x-root | RootOpen.desktop |
Проверка/установка приложения по умолчанию делается вызовом
gio mime ….
Обновлен пакет daqgroup-root. Взята самая свежая версия 6.34.02.
В принципе, есть две сборки. Одна - сборка под Debian12 с сайта CERN, другая была собрана из исходников.
Работа ROOT была проверена (в том числе в среде пакета), всё вроде бы в порядке.
Обновлена утилита crwdep, проверяющая пакетную базу для работы crwdaq.
Напомним, вызов unix crwdep -c выдает
список зависимостей, т.е. пакетов, нужных для работы
crwdaq, с их статусом. При этом выдается список
пакетов, которые еще не установлены. Список удобно копировать для
уставки в консоли. Эта утилита позволит облегчить установку пакета на
рабочих машинах.
В пакет crwkit добавлен сценарий diesel-pascal:
unix diesel-pascal --help # справка
unix diesel-pascal script.lm9 # вызов сценария (--run)
unix diesel-pascal -r script.lm9 # вызов сценария (--run) для выполнения
unix diesel-pascal -d script.lm9 # вызов сценария (--design) для редакции в Дизайнере
unix diesel-pascal -d # вызов Дизайнера (без указания имени проекта)
unix diesel-pascal -q # запрос (--query) текущей привязки MIME типа application/x-diesel
unix diesel-pascal -a # провязка (--assoc) MIME типа application/x-diesel к расширению *.lm9
unix diesel-pascal -u # обновление (--update) привязки MIME типа файла, а также менюУтилита служит для облегчения работы с Дизель Паскалем - вызова интерпретатора/дизайнера, настройки и проверки привязки типов файлов по расширению.
Обновлен инсталляционный пакет
daqgroup-diesel-ext.run. Теперь он должен автоматически
делать CrossMachine обработчиком по умолчанию для
MIME типа файла application/x-diesel с
расширением .lm9.
Это делается командой:
gio mime application/x-diesel CrossMachine.desktop;.
После этого файлы .lm9 должны открываться с помощью
интерпретатора Дизель Паскаль. При этом по щелчку
правой кнопкой на файле .lm9 также доступен вызов
дизайнера.
[[toc]].unix dunstcfg -s работает корректно.unix dunstcfg -t
для тестирования системы оповещения.$(command …).Переходим под ALSE - т.е. AstraLinuxSpecialEdition.
Такую диагностику (в консоль) выдавал при запуске пакет
crwdaq под ALSE. Судя по диагностике,
ошибка возникала при блокировке потоков на критической секции. Возникла
гипотеза, что это связано с выравниванием данных
{$ALIGN …}. Критические секции
использовались в низкоуровневом варианте
TRTLCriticalSection, поэтому выравнивание данных
непосредственно влияло на вызов
pthread_mutex_lock/unlock, на которых работает
TRTLCriticalSection под Linux,
Как показали тесты, гипотеза оказалась верной - эта ошибка исчезала
при включении {$ALIGN ON}. Для устранения
проблемы для TRTLCriticalSection был сделан
класс-обертка TSysCriticalSection.
Он использует выровненные данные, так что вопрос решается. Ценой
является небольшое снижение производительности, связанное с вызовами
функций. Однако это снижение мало и практически не существенно.
С точки зрения программиста для использования безопасных критических
секций достаточно включить в uses модуль
_crw_alloc (который обычно всегда включен)
и заменить переменные типа TRTLCriticalSection на тип
TSysCriticalSection. Остальной код менять, скорее
всего, не придется, т.к. функции для работы с критическими секциями
“перегружены” (overload):
procedure InitCriticalSection(var CritSect:TSysCriticalSection); // Инициализация критической секции
procedure DoneCriticalSection(var CritSect:TSysCriticalSection); // Освобождение критической секции
procedure EnterCriticalSection(var CritSect:TSysCriticalSection); // Вход в тело критической секции
procedure LeaveCriticalSection(var CritSect:TSysCriticalSection); // Выход из тела критической секцииТаким образом, перегрузка функций позволила решить проблему с минимальным числом изменений в коде.
При запуске под ALSE не работала функция GetListOfProcesses (список процессов). Как выяснилось при анализе, причиной было отсутствие файла /proc/pid/sched, откуда считывался приоритет процесса (поле prio). Это связано с тем, что этот файл зависит от опции загрузки ядра CONFIG_SCHED_DEBUG, как описано в статье.
Чтобы не зависеть от этой проблемы, код был модифицирован - при отсутствии файла /proc/pid/sched приоритет вычисляеется другим способом (вызовом функции). Это решило проблему - список процессов стал работать.
Однако есть другие программы (например, Дизель), которые используют файл /proc/pid/sched. Поэтому рекомендуется все-таки включить опцию CONFIG_SCHED_DEBUG.
Чтобы включить эту опцию, надо найти в файле /boot/$(uname -r)
параметр CONFIG_SCHED_DEBUG и вставить строку
CONFIG_SCHED_DEBUG=y
фрагмент
#
# Scheduler Debugging
#
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# end of Scheduler Debugging
заменить на
#
# Scheduler Debugging
#
CONFIG_SCHED_DEBUG=y
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# end of Scheduler Debuggingи затем перегрузиться.
Сделана утилита crtlnk для создания
ярлыков Рабочего Стола. Она вошла в набор
crwkit, а под Windows доступна также в
каталоге resource\shell. Формат утилиты
согласован с утилитой catlnk, так что можно прочитать
ярлык вызовом catlnk, а затем, изменив некоторые поля,
создать новый или переписать старый вызовом crtlnk.
Утилита crtlnk имеет справку
crtlnk --help.
При вызове crtlnk обязательно указание имени создаваемого файла ярлыка - .desktop под Unix или .lnk под Windows. Кроме того, необходимо указать параметры ярлыка - командную строку, имя, комментарий и т.д. - см. таблицу.
Обязательным параметром ярлыка для приложения является только Exec или заменяющая его пара TargetPath, Arguments. Параметр Exec задает полную командную строку для запуска приложения, а пара TargetPath, Arguments задает её в виде пути приложения TargetPath и аргументов Arguments, взятых по отдельности. Список всех параметров - см. таблицу.
Параметры ярлыка можно передавать через аргументы, либо через стандартный канал ввода (stdin). При передаче через канал ввода параметры передаются в формате строк Name=Value, разделенных с помощью EOL. При передаче через аргументы к имени параметра прибавляется признак опции –, а имена параметров переводятся в нижний регистр. Например:
# Создание ярлыка под Linux через аргументы
unix crtlnk demo.desktop --exec 'kate' --name 'Text editor Kate' --category 'Office'
# Создание ярлыка под Linux через канал stdin
printf "Exec=kate\nName=Text editor Kate\nCategory=Office\n" | unix crtlnk demo.desktop
# Создание ярлыка под Windows через аргументы
crtlnk.exe demo.lnk --exec "cmd /c notepad.exe" --comment "Text editor" --showcmd 7
# Создание ярлыка под Windows через канал stdin
unix printf "Exec=cmd /c notepad.exe\nComment=Text editor\nShowCmd=7\n" | crtlnk.exe demo.lnkСоздание ярлыка через аргументы удобно, когда создается новый ярлык с вычисляемыми параметрами. Создание ярлыка через канал удобно, когда редактируется существующий ярлык. Тогда его можно прочитать вызовом catlnk, модифицировать в потоке (например, редактором sed) и передать в канал crtlnk. В общем, оба метода будут полезны на практике.
| Параметр | Тип | Система | Пояснение |
|---|---|---|---|
| Type | s | X | Тип ярлыка: Application, Link, Directory. см. XDG. |
| Version | s | X | Версия спецификации. см. XDG. |
| Name | ls | X | Отображаемое имя приложения для ярлыка. см. XDG. |
| GenericName | ls | X | Обобщенное имя (Браузер, Редактор и т.д.). см. XDG. |
| NoDisplay | b | X | Отключает ярлык (он не отображается). см. XDG. |
| Comment | ls | X,Win | Комментарий подсказки во всплывающем окошке. см. XDG. |
| Description | ls | Win | Синоним Comment. |
| Icon | s | X,Win | Имя иконки (изображения) ярлыка. см. XDG. |
| IconLocation | s | Win | Синоним Icon. |
| Hidden | b | X | Флаг “Скрытный запуск, без видимого окна”. см. XDG. |
| OnlyShowIn | s | X | Список оболочек, где отображается ярлык. см. XDG. |
| NotShowIn | s | X | Список оболочек, где ярлык не отображается. см. XDG. |
| DBusActivatable | b | X | Флаг возможности активации через DBus. см. XDG. |
| TryExec | s | X | Файл, проверяемый перед запуском ярлыка. см. XDG. |
| Exec | s | X,Win | Командная строка для запуска приложения. см. XDG. |
| TargetPath | s | X,Win | Команда для запуска приложения (вместе с Arguments, вместо Exec). |
| Arguments | s | X,Win | Аргументы командной строки (вместе с TargetPath, вместо Exec). |
| Path | s | X,Win | Рабочий каталог для запуска приложения. см. XDG. |
| WorkingDirectory | s | Win | Синоним Path. |
| Terminal | b | X | Флаг “Выполнять команду в терминальном окне”. см. XDG. |
| Actions | s | X | Список дополнительных действий. см. XDG. |
| MimeType | s | X | MIME тип файла. см. XDG. |
| Categories | s | X | Список категорий для размещения ярлыка (для меню). см. XDG. |
| Keywords | ls | X | Список ключевых слов. см. XDG. |
| StartupNotify | b | X | Флаг “Оповещение при старте.”. см. XDG. |
| StartupWMClass | s | X | Имя класса окна. см. XDG. |
| URL | s | X | Адрес ссылки для ярлыка типа Link. см. XDG. |
| Hotkey | s | Win | Горячая клавиша для вызова ярлыка. |
| ShowCmd | i | Win | Команда отображения окна. см. ShowCmd. |
| WindowStyle | i | Win | Синоним ShowCmd. |
Примечания:
Утилита crtlnk создана для программной генерации ярлыков Рабочего Стола. Например, для редактирования ярлыков меню вызова сессий пакета crwdaq.
Обновлен сценарий crwdaqwatcher.sh для анализа журнального файла пакета. Его работа значительно оптимизирована (ускорена), снижена загрузка CPU.
Сделан вариант сценария crwdaqwatcher.cmd для Windows.
Теперь по завершении работы пакета утилита crwdaqwatcher анализирует журнал и определяет статус завершения процесса:
В начало справочного файла добавлены ссылки на полезные разделы, которых явно там не хватало. Пользоваться справкой станет удобнее.
Подготовлен первый релиз crwdaq, пригодный для практического использования.
Сборка сделана под Astra Linux Common Edition и под Win32.
Свершилось!
Создана диагностическая утилита crwdaqwatcher.sh -
“наблюдатель для crwdaq”.
Она запускается в сценарии crwdaq.logon.sh при старте
сессии crwdaq и наблюдает за процессом.
При завершении процесса crwdaqwatcher анализирует файл
leakage.log и определяет статус завершения:
По результатам диагностики выдается всплывающее сообщение и делается запись в журнале crwdaqwatcher.log.
Утилита crwdaqwatcher служит для диагностики проблем с пакетом, позволяя обнаружить и обратить внимание на эти проблемы.
Пока утилита сделана только под Unix. Версия под Windows выйдет позже.
Во многих местах DAQ системы регистр имен файлов под
Windows приведен к нижнему.
Для Unix это и так уже было сделано. Надеюсь, это не
вызовет ошибок в прикладном ПО.
Добавлена переменная CRW_DAQ_SYS_SESSION_HEAD. Это
название текущей сессии работы программы. Включает имя программы и номер
сеанса. Типичное значение crwdaq_1.
Переменная полезна для формирования сообщений, имен файлов и т.д.
SKIP_DRAFT.Продолжение подготовки к первому релизу. В основном мелкие поправки.
Привязка диалогов ввода имени файлов к кнопкам.
Поправки, связанные с регистром имен файлов при сохранении
данных.
Под Windows в некоторых местах при сохранении
получались файлы с именами в верхнем регистре.
Теперь данные сохраняются в файлы с именами в нижнем регистре, согласно
принятым правилам.
Хотя под Windows разницы нет, лучше придерживаться
единых правил,
так как эти файлы могут использоваться также и под
Unix.
Идет плановая подготовка к первому релизу. В основном мелкие поправки.
Мелкие (но многочисленные) поправки в привязке диалогов.
При активизации главного окна также активизируется окно “DAQ-система” (после загрузки DAQ).
Шла плановая подготовка к первому релизу. В основном мелкие поправки.
В редакторе текста на панель инструментов добавлены кнопки
“Файл/Сохранить” и
“Файл/Печать”. Это сделано для удобства,
т.к. эти часто используемые кнопки и должны быть под рукой. Искать эти
кнопки в общем меню бывает неудобно.
Сделана привязка большого числа диалогов, связанных с
DAQ системой, к соответствующим кнопкам в управляющем
окне DAQ Система. Это удобнее, чем
привязка диалогов к центру экрана, т.к. диалог появляется вблизи того
места, где была нажата кнопка.
В большом количестве мест выражение
not IsEmptyStr() заменено на новую функцию
IsNonEmptyStr(). Это улучшает
читабельность и ясность кода, т.к. условия с отрицаниями воспринимаются
труднее и создаются предпосылки для логических ошибок.
По предложению Н.Гурина поправлен диалог чтения .dat
файлов.
Теперь он может менять размеры, чтобы (длинные) надписи умещались в
окне.
Кроме того, сделана привязка диалога к кнопке “Открыть
файл”, чтобы было удобнее.
Мелкие правки и дополнения в документацию. Список пожеланий todo. Справка по плагинам plugin. И другие темы.
При компиляции в окне редактора DaqPascal сделано всплывающее уведомление, чтобы было видно статус компиляции.
Исправлены замеченные Н.Гуриным недочеты в TrayIcon:
Неверная иконка была просто явной ошибкой, а надписи действительно стали более понятными.
В DaqPascal добавлены функции AdaptDllFileName, AdaptLnkFileName. Они нужны для адаптации имен файлов динамических библиотек .dll и ярлыков Рабочего Стола .lnk.
Напомним, что:
Под Windows библиотеки имеют имена
*.dll, а ярлыки -
*.lnk.
Под Unix библиотеки имеют имена
lib*.so, а ярлыки -
*.desktop.
Соответственно функции адаптации имен файлов приводят имена к нужному для данной платформы виду.
Скорректирован код программы стандартной библиотеки _dllwrap.pas. Коррекция связана с кроссплатформенностью (адаптация имен файлов библиотек). Программа служит “оберткой” для вызова DLL плагинов. Имеется справка _dllwrap.htm.
В стандартной библиотеке обновлены функции DLL_INIT, DLL_FREE, DLL_POLL. В них улучшена диагностика, контроль ошибок.
Добавлены функции STD_DLL_INIT, STD_DLL_FREE, STD_DLL_POLL.
Разница состоит в том, что функции
DLL_INIT/FREE/POLL работают с явной
ссылкой на библиотеку DLL, для которой требуется
заводит переменную и следить за её состоянием. Требуется явно вызывать в
пользовательском коде инициализацию
DLL_INIT, завершение
DLL_FREE и опрос
DLL_POLL.
А вот функции STD_DLL_INIT/FREE/POLL
работают с готовой (библиотечной) ссылкой STD_DLL_REF, за которой
уже следит библиотека. Вызовы завершения
STD_DLL_FREE и опроса
STD_DLL_POLL уже встроены в код
стандартной библиотеки. Пользователю требуется только вызвать функцию
STD_DLL_INIT для инициализации библиотеки
при старте программы. Таким образом код обслуживания
DLL плагина сводится к одной строчке - инициализации
плагина вызовом STD_DLL_INIT. В этом
механизме есть только один недостаток - предопределенный алгоритм работы
плагина. Это просто вызов STD_DLL_POLL в
(каждом) цикле опроса и вызов STD_DLL_FREE
при завершении работы DAQ-конфигурации. Если требуется
более сложная обработка, связанная с плагином (например, вызов плагина
по событию, а не в каждом цикле опроса), то стандартная обработка должна
быть заменена на пользовательскую с использованием функций
DLL_INIT/FREE/POLL.
Создана альтернативная программа стандартной библиотеки _dllhost.pas.
Программа служит “оберткой” для вызова DLL плагинов.
Она написана на базе функций стандартной библиотеки и более корректно,
чем программа _dllwrap.pas, диагностирует
и обрабатывает ошибки. Она станет рекомендуемой заменой программы
_dllwrap.pas, которая теперь считается
“устаревшей” или “запасной”. Имеется справка _dllhost.htm.
Существенно дополнена справка по плагинам crwdaq-plugin.htm.
Этой справки достаточно, чтобы получить начальное представление
плагинах,
а наличие примеров облегчит создание новых плагинов.
Добавлен параметр
crwdaq.ini [System] RunCommandPipeSizeKb = 64.
Это размер буфера PipeBufferSize в килобайтах,
используемый для вызова RunCommandEx.
В библиотеке Free Pascal есть функция
RunCommand(…) для вызова команд ОС с
перехватом их консольного вывода. Эта команда используется во многих
местах, в частности, для реализации подстановок
$(…), добавленных недавно. У “штатной”
реализации команды RunCommand есть ряд недостатков:
Время выполнения команды не ограничено.
Это создает возможность “повесить” программу на ожидании завершения
команды.
Нет возможности задавать режим отображения окна.
Поскольку под Windows при вызове команды создается
видимая консоль,
из-за этого возникает неприятное “мелькание” окон на экране при
выполнении команд.
При длительном выполнении команды ожидающий поток создает высокую
нагрузку процессора.
Это потому что цикл ожидания не вызывает Sleep -
предпочтение отдается минимизации
времени выполнения команды, а не минимизации нагрузки
CPU.
По этой причине было решено сделать альтернативную функцию RunCommandEx, в которой есть предельное время ожидания TimeOut, режим отображения окна и другие “плюшки”.
Чтобы не трогать старые коды, где уже используется
RunCommand, реализация RunCommand
изменена. Её поведение зависит от переменной выбранного режима
rcm_Selected (run command mode
selected). В режиме rcm_Standard
работает стандартная версия RunCommand, а в режиме
rcm_Extended - версия
RunCommandEx.
В файле настроек crwdaq.ini заведены параметры, управляющие поведением RunCommand:
AlwaysUseRunCommandEx = 1 ; Use RunCommandEx always, instead of RunCommand.
RunCommandSleepTime = 4 ; Sleep time [ms] during RunCommandEx waiting loop.
RunCommandTimeOut = 15000 ; Timeout [ms] to wait RunCommandEx execution.
RunCommandSwo = ShowMinNoActive ; RunCommandEx default ShowWindowOption.| Параметр | Значение | Комментарий |
|---|---|---|
| AlwaysUseRunCommandEx | 1 | Флаг “Всегда использовать RunCommandEx вместо RunCommand.” |
| RunCommandSleepTime | 4 | Время (ms) “засыпания” в цикле ожидания завершения команды. |
| RunCommandTimeOut | 15000 | Время (ms) максимально допустимого ожидания завершения команды. |
| RunCommandSwo | ShowMinNoActive | Режим окна при вызове команды (актуально для Windows). |
Режим окна RunCommandSwo может принимать значения
Hide, Maximize,
Minimize, Restore,
Show, ShowDefault,
ShowMaximized, ShowMinimized,
ShowMinNoActive, ShowNA,
ShowNoActivate, ShowNormal.
Приведенные параметры позволяют гибко настраивать поведение
RunCommand.
Параметр AlwaysUseRunCommandEx включает расширенный
режим RunCommandEx.
Параметр RunCommandTimeOut ограничивает время
выполнения команд в расширенном режиме.
Это предохраняет программу от зависания в случае недопустимо длительного
выполнения команд.
Параметр RunCommandSleepTime задает частоту опроса в
цикле ожидания завершения команды.
Параметр RunCommandSwo задает режим окна при выполнении
команды.
Это позволяет устранить “мелькание” окон при выполнении команд.
Реализована простая система FileGuard для защиты файлов пакета от нежелательного редактирования.
Как уже упоминалось в предыдущем сообщении, целью защиты является предохранение от случайных ошибок оператора, а не защита от злоумышленников. Поэтому защита “слабая”, на уровне интерфейса пользователя, а не на уровне прав доступа файловой системы и OS.
Защита описывается в секции System.FileGuard.Protection. В этой секции содержится таблица шаблонов имен файлов, которые рассматриваются как защищенные - ReadOnly. Таблица имеет проимерно такой вид:
[System.FileGuard.Protection]
ReadOnly = ~~/. crwdaq.ini
ReadOnly = ~~/resource *.ini *.cmd *.sh *.lm9
ReadOnly = ~~/resource/plugin/dan/* _*.lpr
ReadOnly = ~~/resource/plugin/daq/* *.lpr
ReadOnly = ~~/resource/sample/* *.lpr
ReadOnly = ~~/resource/daqsite/* *.pas *.inc *.lm9
[]Формат таблицы:
ReadOnly = Directory Mask1 Mask2 …, где
Directory - каталог расположения или
каталог/*. Если указан простой каталог, то
файлы ищутся только в нём (нерекурсивно). Если в конце каталога стоит
звездочка /*, то поиск идет рекурсивно,
т.е. с подкаталогами. После каталога задается одна или несколько масок
поиска файлов (Mask1,
Mask2, …). Защищенным считается файл,
соответсвующий любому из приведенных в таблице шаблонов.
Защита
[System.FileGuard.Protection] ReadOnly
заключается в том, что встроенный редактор текста будет работать в
режиме ReadOnly (только чтение) и будет
отказыватся переключаться в режим редактирования, если файл защищен
(удовлетворяет одному из шаблонов таблицы). Таким образом, из среды
пакета редактировать защищенный файл будет нельзя.
Защита ReadOnly включается в окне Главной Консоли функцией EnableFileGuard:
EnableFileGuard(0) # Отключить защиту
EnableFileGuard(1) # Включить защиту - по умолчанию включена
x=EnableFileGuard(_nan) # Прочитать состояние защиты без измененияПо умолчанию защита включена, она отключается только для отладок. Обычные пользователи не должны использовать эту команду и даже знать о ней.
Файлы стандартной библиотеки DAQ системы
~~/resource/daqsite/* *.pas дополнительно
защищены флагом EnableEditDaqSite(0), который по
умолчанию сброшен в 0. То есть для этих файлов работает
двойная защита. В принципе, вторая защита (сделанная ранее) теперь не
очень нужна, но удалять её я не стал, дополнительная защита не
помешает.
Заведен модуль _crw_flgrd.pas для
защиты файлов (file guard).
По замыслу, в этом модуле будут собраны функции, относящиеся к защите
важных файлов пакета от случайного изменения. Это будет не столько
защита уровня OS и прав доступа файлов, сколько защита
на уровне пользовательского интерфейса.
Пока реализована защита System.FileGuard.Replacement. Идея такая. В файле конфигурации описана таблица замены имен файлов:
[System.FileGuard.Replacement]
ReplaceDirectory = ~~/temp $CRW_DAQ_VAR_TMP_DIR/temp
ReplaceDirectory = ~~/data $CRW_DAQ_VAR_TMP_DIR/data
[]Например, файл ~~/temp/test.log будет
заменен на
$CRW_DAQ_VAR_TMP_DIR/temp/test.log.
Замены имен применяются в ряде мест программы - например, в команде
@log или при формировании путей для
рабочих каталогов при загрузке конфигурации
DAQ-системы. Эти замены защищают каталог программы
~~\ от записи туда всяких служебных файлов
- журналов, отладочных файлов, файлов данных и т.д. Защита потребовалась
потому, что в новой системе организации работы (менеджер сессий) каталог
пакета должен оставаться неизменным, чтобы избежать конфликта запущенных
экземпляров программы. В то же время некоторые прикладные конфигурации
использовали каталоги типа ~~/temp для
хранения служебных файлов. Вопрос расположения служебных файлов обычно
не критичен для прикладного кода - каталоги для журналов могут быть где
угодно. Поэтому, чтобы не переделывать прикладной код, делается замена
имен служебных файлов на уровне библиотек пакета.
В результате замены имен служебные файлы создаются, но в другом (безопасном) месте, согласно таблице замен.
В функции ExpEnv для подстановки
переменных окружения реализована также подстановка вывода команд в стиле
bash, с использованием конструкции
$(command). Эти подстановки доступны
везде, где были подстановки $переменных,
только в некоторых случаях потребуются кавычки, чтобы передавать команду
полностью, без разбивки на слова. Например, теперь можно написать в окне
Главной Консоли:
@GetAppPath "$(unix which lhelp)" -c xchm --run demo.chm
# для запуска demo.chm будет выбран либо результат
# команды 'unix which lhelp', либо программа xchm.Новое средство весьма мощное, обращаться с ним надо аккуратно.
Под Windows новое средство имеет ограниченную пользу, т.к. там не так много полезных команд с вменяемым выводом. Кроме того, при вызове команд создается и мелькает на экране консольное окно cmd. Поэтому новое средство полезно в основном под Unix.
В crwkit добавлена программа pasdoc. Она умеет создавать документацию по исходным кодам программ на языке Free Pascal, извлекая её из текста и комментариев программ.
Пока это только потенциальная возможность. Предварительное тестирование показало, что создание справки с помощью pasdoc возможно, но требует серьезной проработки, т.к. комментарии для создания справки следует писать по определенным правилам.
В случае успешной проработки этого вопроса возможно будет получить качественную документацию для crwlib, crwdaq, а возможно и для библиотек и программ DaqPascal.
Альтернативой является использование fpdoc - встроенной в lazarus программой. Она хорошо умеет создавать структуру модулей/классов/функций. Однако она не умеет извлекать из комментариев описание модулей/классов/функций, а вместо этого требует подготовки отдельных xml файлов описаний. Поэтому вопрос автоматичекой генерации документации пока требует проработки.
На данный момент в пакет включена справка crwlib, сгенерированная fpdoc - то есть справка, позволяющая быстро находить функции с аргументами, но без описаний. Даже такая справка полезна, т.к. многое понятно по именам функций и параметров. Возможно, удастся сделать генератор xml описаний из комментариев. Пока кажется, что обе системы fpdoc и pasdoc будут востребованы для разных задач. Но всё это потребует определенных усилий.
Проведены массовые замены {$I xxx.pas}
на {$I xxx.inc}.
Все включаемые файлы, имевшие расширение
*.pas - стали
*.inc. По традиции Free
Pascal включаемые файлы имеют расширение .inc.
На это ориетируются некоторые инструменты анализа кода и подготовки
документации. Поэтому лучше придерживаться традиции.
NB: Пользователи crwlib должны будут поправить свои коды по приведенным в документа рекомендациям в связи с этими изменениями.
Канонический шаблон модуля: _crw_xxxx.pas.
Массовые замены {$I xxx} на {$I
xxx.pas}.
Это работало потому что использовалось расширение по умолчанию
.pas.
Но лучше указывать его явно. К тому же справочная система
fpdoc требует указания расширений.
Проводилась доработка справки по crwlib и сценариев
crwlazhelp(.sh|.cmd).
Теперь справки открываются корректно, избегая дублирования при открытии
окон.
То есть если лкно справки открыто, оно активируется.
Кажется, в первом приближении средства разработки и поддержки плагинов и консольных драйверов готовы.
В дистрибутиве FPC найдена полезная утилита fpcdoc, которая умеет делать справку по модулям Free Pascal из исходников. С использованием fpcdoc создан сценарий crwlib-fpcdoc.sh, создающий справку для crwlib. Это полезно, т.к. crwlib используетсяв том числе для создания плагинов.
Небольшие доработки в диалоге вызова плагинов обработки данных.
В окна редактора проектов .lpr добавлена команда вызова справки по CrwLib. Это будет полезно при разработке плагинов и консольных драйверов в среде пакета. Реализация справки имеет недостатки, главным из которых является отсутсвие контекстного поиска по ключевому слову. То есть информацию надо искать по ссылкам в гипертексте. Но главное что есть где искать.
В справке по CrwLib есть ссылка на CrwApi - библиотеку модуля интерфейса для программирования плагинов. В этом модуле определены все функции, предоставляемые плагину для взаимодействия с пакетом.
Сделан модуль _crw_uses_first.
Он содержит список модулей, которые, как следует из названия, должны
включаться первыми в секции uses любого модуля или
программы. Это ссвязано с тем, что корректная работа Менеджера
Памяти, а также поддержка многопоточного
режима требуют обязательного включения в каждый модуль
определенных юнитов ПЕРВЫМИ, чтобы они успели
инициализироваться до того, как потребуется выделять память или
создавать потоки. Эту задачу и выполняет модуль
_crw_uses_first.
С учетом нового модуля каждый uses в любом модуле проекта crwlib, crwdaq делается по шаблону:
uses
//////////////////////////////////////////////////////
{$I _crw_uses_first.inc} // NB: MUST BE FIRST USES !!!
//////////////////////////////////////////////////////
sysutils, classes, math,
… и так далее …Введение шаблона uses позволит при необходимости изменить состав “первоочередных” модулей, сделав изменения в одном файле.
Все исходные файлы проекта были переделаны под шаблон
_crw_uses_first.
Изменения коснулись сотен файлов .pas, .lpr. Вроде бы замена эквивалентная - просто кусок текста вынесен в отдельный файл. Однако, на всякий случай, надо быть готовым к неожиданнастям.
В папке resource/plugin/daq заведены плагины
для DAQ-систем.
Пока там шаблон demo_dll_sin_plugin и
demo_dll_min_plugin.
В CrwAPI добавлено еще много функций, в основном для поддержки DAQ системы.
Практически все плагины, включая шаблоны и плагины dan для анализа данных, были отредактированы в пакетном режиме. Более компактно и корректно сделана проверка типа плагина, добавлена проверка версии плагина, чтобы избежать проблем при обновлении CrwApi.
Доработана системв плагинов для DAQ.
Для проверки её работы демо DEMO_DLL из
crw32 переработано в демо demo_dll_sin.
Демо работает нормально, проверка на утечки памяти прошла успешно.
Плагин из этого демо будет взят как шаблон для других
daq плагинов сбора данных.
В CrwAPI добавлено еще много функций (порядка 50), для полноты набора.
Заведен файл справки по разработке плагинов crwdaq-plugin.htm.
Пока там минимальная информация (о типах плагинов). По мере возможности справка будет доработана, чтобы прикладные программисты могли сами создавать нужные в прикладных задачах плагины.
Продолжалась доработка (расширение функций) команды @wmctrl, а также
утилиты wmquery.
Поскольку они основаны на вызове одной функции
wmctrl_query, достаточно рассмотреть одну
из них.
Добавлены такие операции:
wmquery ShowWindow -title KCalc -sw ShowNormal
# показать окно в режиме отображения ShowNormal
# возможные режимы отображения (-sw …) такие:
# HIDE,SHOWNORMAL,SHOWMINIMIZED,SHOWMAXIMIZED,
# SHOWNOACTIVATE,SHOW,MINIMIZE,SHOWMINNOACTIVE,
# SHOWNA,RESTORE,SHOWDEFAULT
wmquery ShowWindow -title KCalc # показать окно
wmquery HideWindow -title KCalc # спрятать окно
wmquery MinimizeWindow -title KCalc # свернуть окно
wmquery MaximizeWindow -title KCalc # развернуть на максимум
wmquery RestoreWindow -title KCalc # восстановить (показать) окно
wmquery ListModes # печать списка режимов ListWindowsФактически это разные варианты функции ShowWindow с разными режимами отображения. Все эти операции можно делать вызовом ShowWindow с указанием режима отображения, но для упрощения программного интерфейса наиболее распространенные режимы реализованы отдельной операцией.
На низком уровне вызовы ShowWindow транслируются в команды изменения состояния окна SetWindowStateList, но это выгляядит довольно громоздко и непонятно. Вызовы ShowWindow короче, привычнее и потому понятнее.
К сожалению, довольно трудно добиться совершенно одинаковой работы команд ShowWindow в Unix и Windows, в силу существенной разницы в терминологии и деталей реализации. Например, режим SHOWNOACTIVATE (показать окно, но не делать его активным) под Linux реализовать пока не удалось, он фактически работает как SHOWNORMAL.
В общем, хотя команды работают в целом одинаково, небольшие различия под Linux и Windows есть, и это надо иметь в виду.
В интерпретатор Главной Консоли добавлена команда @sig для работы с сигналами Unix.
@sig -name 15 # узнать имя сигнала 15
> SIGTERM
@sig -code TERM # узнать код сигнала TERM
> 15
@sig -list # получить список сигналов
> 1) SIGHUP
> 2) SIGINT
> .. и т.д.
@sig -kill 2315 -s TERM # послать SIGTERM процессу 2315
@sig -kill xterm -s INT # послать SIGINT процессу xtermПод Windows сигналы (частично) моделируются, по мере
возможности. Например, SIGINT посылает
^C, а SIGTERM - посылает
WM_CLOSE. Но, разумеется, полная
совместимость по сигналам недостижима, т.к. сигналы - это всё-таки
специфика Unix, доступная под Windows
только частично.
Команда полезна как для справки по сигналам Unix, так и для взаимодействия с другими процессами - как наипростейший метод IPC.
В CrwAPI заложено большое число функций, с запасом на будущее. Пока, на данном этапе развития, этого будет достаточно.
Можно констатировать завершение работы по переводу плагинов для обработки данных. Плагине теперь реализованы на интерфейсах, используют длинные строки и полностью работоспособны.
Остается еще перевести и проверить работу плагинов сбора данных. Это будет делаться в ближайшее время.
В crwlib и CrwApi добавлена функция wmctrl_query.
Эта функция инкапсулирует (содержит в себе) множество функций для работы с Менеджером Окон, называемого wmctrl (window manager control).
Менеджер окон wmctrl управляет Окнами (window), расположенными на одном или нескольких Рабочих Столах (desktop) операционной системы. Он позволяет находить окна, менять их положение и состояние, перемещать окна, закрывать и убивать их (завершать их работу).
В интерпретаторе Главной Консоли добалена команда
@wmctrl, которая дает удобный доступ
к функции wmctrl_query. Это делает
доступным функции оконного менеджера в программах
DaqPascal, который может посылать в Главную
Консоль команду @wmctrl.
Синтаксис команды @wmctrl довольно сложен, т.к. в ней содержится много функций:
@wmctrl
Syntax:
@wmctrl -query DisplayInfo -mode m
@wmctrl -query XlibInfo -mode m
@wmctrl -query ListWindows -pid p -class "c" -title "t" -mode m
@wmctrl -query FindWindow -pid p -class "c" -title "t" -index i
@wmctrl -query WindowManagerName
@wmctrl -query DesktopCount
@wmctrl -query ActiveDesktop
@wmctrl -query SwitchToDesktop -desktop d
@wmctrl -query ActiveWindow
@wmctrl -query ActivateWindow -wnd w -switch-desktop s
@wmctrl -query WindowPid -wnd w
@wmctrl -query WindowDesktop -wnd w
@wmctrl -query WindowHost -wnd w
@wmctrl -query WindowTitle -wnd w
@wmctrl -query WindowClass -wnd w
@wmctrl -query WindowBounds -wnd w
@wmctrl -query WindowStateList -wnd w
@wmctrl -query WindowTypeList -wnd w
@wmctrl -query WindowStateFlags -wnd w
@wmctrl -query WindowTypeFlags -wnd w
@wmctrl -query SetWindowStateList -wnd w -wsc c -state-list l
@wmctrl -query SetWindowStateFlags -wnd w -wsc c -state-flags f
@wmctrl -query SetWindowDesktop -wnd w -desktop d
@wmctrl -query SetWindowTitle -wnd w -title "t"
@wmctrl -query SupportedList
@wmctrl -query MoveResizeWindow -wnd w -geom g
@wmctrl -query CloseWindow -wnd w -timeout t
@wmctrl -query KillWindow -wnd w -sig s -timeout t
@wmctrl -query IcccmClass
@wmctrl -query ListDesktopManagers
@wmctrl -query DesktopManager -index i
@wmctrl -query ListTerminals
@wmctrl -query Terminal -index i
Notes:
1) Option -wnd w mostly can be replaced to combination of
other options: -pid p -class "c" -title "t" to find window.
This feature uses to work with pid/class/title instead of wnd.
2) Short option parameters explanation:
-mode m - operation mode, depends on command
-index i - index of window to find, 0-based
-desktop d - desktop number to switch
-switch-desktop s - flag (0/1) to switch desktop on activate window
-wnd w - target window handle
-win w - target window handle
-pid p - target window process ID to find
-class "c" - target window class name to find
-title "t" - target window title text to find
-state-list l - window state list, subset of items:
MODAL,STICKY,MAXIMIZED_VERT,MAXIMIZED_HORZ,
SHADED,SKIP_TASKBAR,SKIP_PAGER,HIDDEN,FULLSCREEN,
ABOVE,BELOW,DEMANDS_ATTENTION,FOCUSED
-state-flags f - bit flags corresponded to state-list
-wsc c - window state command 0/1/2=remove/add/toggle
-geom g - geometry for MoveResize: g,x,y,w,h
g:gravity=0, x,y=left,top, w,h=width,height
-timeout t - timeout for close/kill window, ms
-sig s - signal number or name to kill window
-wndfmt f - format of wnd to print: 0:%d,1:%u,2:0x%x,3:$%x
-inst i - instance name for IcccmClass
Example:
@wmctrl -query ListWindows -mode 1
@wmctrl -query ActivateWindow -title "KCalc"
wnd=@wmctrl -query FindWindow -title "KCalc"
@wmctrl -query KillWindow -wnd %wnd -sig TERM
@wmctrl -query KillWindow -title "KCalc" -sig TERM
@wmctrl -query MoveResizeWindow -title "KCalc" -geom 0,100,200
@wmctrl -query SetWindowStateList -title "KCalc" -wsc 1 -state-list HIDDENПримеры использования (для примера взят калькулятор kcalc):
# Узнать информацию о дисплее, Xlib
@wmctrl -query DisplayInfo
@wmctrl -query XlibInfo
# Список доступных оконных менеджеров и текущий менеджер
@wmctrl -query ListDesktopManagers
@wmctrl -query DesktopManager
# Список доступных программ-терминалов и терминал по умолчанию
@wmctrl -query ListTerminals
@wmctrl -query Terminal
# Найти окно по заголовку и затем убить его
wnd=@wmctrl -query FindWindow -title "KCalc"
@wmctrl -query KillWindow -wnd %wnd -sig TERM
# Активировать окно с поиском по заголовку
@wmctrl -query ActivateWindow -title "KCalc"
# Поиск окна по PID и имени класса
wnd=@wmctrl -query FindWindow -pid 21571 -class "kcalc.kcalc"
# Минимизировать (спрятать) окно - т.е. задать состояние HIDDEN
@wmctrl -query SetWindowStateList -title "KCalc" -wsc 1 -state-list HIDDEN
# Восстановить (показать) окно - т.е. отменить состояние HIDDEN
@wmctrl -query SetWindowStateList -title "KCalc" -wsc 0 -state-list HIDDENКоманда wmctrl будет полезна для организации “гибридных” систем, включающих несколько независимых программ, взаимодействующих друг с другом через сообщения и другие механизмы IPC. Она позволит управлять окнами других (внешних) программ, добиваясь необходимого поведения всего программного комплекса.
В сборку crwkit добавлена программа wmquery.
Она является оболочкой для вызова функции
wmctrl_query и нужна для работы в
сценариях bash.
Например:
unix wmquery --help
unix wmquery --version
unix wmquery ActivateWindow -title "KCalc"
unix wmquery SetWindowStateList -title "KCalc" -wsc 1 -state-list HIDDENУправление окнами из сценариев бывает нужно для организации программных комплексов из автономных программ, которые работают совместно для решения общей задачи.
В настоящее время реализация wmquery несовершенна. Например, под Unix не срабатывает команда CloseWindow (причина неизвестна - но похоже на то, что она не поддерживается), а под Windows - реализованы не все команды SetWindowStateList - точнее, пока работает только изменение состояния HIDDEN. Это связано с неполной реализацией wmctrl - некоторые возможности реализованы не до конца. Причиной является проблема “проекции” состояний окон Windows и Unix из-за разной терминологии. Окна Windows оперируют терминами (iconic,zoomed,visible,…), а окна Unix - состояниями (hidden,skip_taskbar,fullscreen,…). Как они друг другу соответствуют, не до конца понятно. Будер разбираться. Это будет дорабатываться в рабочем порядке.
Команда wmquery достаточно мощная и универсальная. Со временем она может заменить почти весь набор из многих команд для работы с окнами. Но это произойдет со временем, когда все недостатки wmquery будут устранены.
Добавлено много (более 200) функций в CrwApi.
Ставится цель заложить в CrwApi максимум возможностей
на будущее.
Среди функций много знакомых по DaqPascal -
task_xxx, pipe_xxx и другие.
Это позволит создавать плагины и программы DaqPascal в
едином стиле.
В интерфейсы CrwAPI добавлено
большое (более сотни) число функций.
В основном это функции обработки строк и файлов.
Переработан и доведен до рабочего состояния плагин _root_hist_1d.
Это плагин для построения гистограм распределения значений кривой с
фитированием по Гауссу.
Для фитирования используется пакет ROOT. Теперь это
должно работать.
С переводом кода на C++ в ROOT
возникли проблемы.
Они связаны с тем, что ROOT раньше использовал
интерпретатор CINT, а теперь другой интерпретатор на
основе LLVM. Эти интерпретаторы имеют мелкие
несовместимости. Пакет ROOT под Win32
работает на CINT (пока не обновлялся). А под
Linux - на LLVM. Код удалось сделать
рабочим на обоих версиях с использованием
#ifdef __CINT__.
Все классы CrwAPI переведены в
интерфейсы.
Это сделает бинарные (ранее скомпилированные) плагины независимыми от
версии FPC,
на которой они скомпилированы. Это избавит нас от многих проблем в
будущем.
Все строки CrwAPI переведены с
ShortString в LongString.
Это снимает ограничения на длину строк в большинстве функций.
Ограничение продолжает действовать в следующих случаях:
В набор функций CrwAPI добавлены функции идентификации системы типа IsUnix, IsWindows и подобные им. В ближайшее время добавление функций продолжится до уровня, необходимого для создания кроссплатформенных плагинов.
Исправлена серьезная ошибка в реализации TInterfacedMasterObject. После исправлений модуль проверен и работает нормально.
Еще два класса стали интерфейсами - IScriptInterpreter, IRfaDataBaseWrap. Использовавшие их плагины поправлены и проверены. Еще в этих интерфейсах проведена замена ShortString ➔ LongString.
Сделан модуль _crw_if_masters.pas, в котором определены классы, использующие интерфейсы в различных вариантах:
Библиотека понадобилась для перевода плагинов на интерфейсы.
Система плагинов crw32 была привязана к классам, т.к. реализовалась через виртуальные методы. Это вполне рабочая схема, но её недостатком является то, что такая реализация классов зависит от версии компилятора. Если пакет откомпилирован в одной версии FPC, а плагин в другой версии, может возникнуть двоичная несовместимость (если таблица виртуальных функций изменилась) с последующей аварийной ситуацией.
Решением этой проблемы является использование интерфейсов, которые специально разрабатывались для решения этой проблемы (двоичной совместимости библиотек).
Поэтому было решено переделать CrwAPI плагинов с классов на интерфейсы.
Основные интерфейсы CrwApi, SysApi, GuiApi, DaqApi, DanApi реализованы по схеме TNoRefCountMasterObject без подсчета ссылок, что в данном случае удобнее обычной для интерфейсов техники ссылок. Зато при отказе от подсчета ссылок плагин не сможет удалять объекты, которые он не создавал. Это повысит защищенность кода плагинов.
Пока реализованы только основные, наиболее важные и часто
используемые интерфейсы.
В CrwAPI еще остались объекты, требующие замены на
интерфейсы - так что работа будет продолжена.
Важно, однако, что тестирование показало работоспособность кода с
интерфейсами, так что проблем не ожидается.
Велась доработка плагинов и шаблонов для них.
В CrwApi добавлено несколько функций идентификации плагина:
Идентификация плагина нужна в некоторых случаях для диагностики или поиска файлов.
Проводились мелкие доработки скриптов для плагинов.
Заведен файл справочной информации на тему unicode.
Там в частности таблица часто используемых в практике символов для
копирования.
А то надоело лазить по справочникам. Тем более что в практике
программирования
сравнительно часто используется менее пары десятков спецсимволов.
Продолжена работа над плагинами. В сценарии
crwlazclone.sh сделана защита,
которая препятствует помещению в каталог плагинов
plugin/dan проектов другого типа.
Это нужно чтобы избежать путаницы при генерации проектов.
В команде @run … поправлена (улучшена)
опция -cd ….
Эта опция задает каталог запуска для программы.
Теперь там можно задавать:
| Ссылка | Содержание |
|---|---|
~ |
Домашний каталог пользователя $HOME
или %UserProfile%. |
~~ |
Домашний каталог программы
$CRW_DAQ_SYS_HOME_DIR. |
Например:
@run -cd ~ xterm # запуск xterm в каталоге пользователя $HOME
@run -cd ~~ xterm # запуск xterm в каталоге программы $CRW_DAQ_SYS_HOME_DIR
# раньше приходилось бы писать:
@run -cd $HOME xterm # запуск xterm в каталоге пользователя $HOME
@run -cd $CRW_DAQ_SYS_HOME_DIR xterm # запуск xterm в каталоге программы $CRW_DAQ_SYS_HOME_DIRНовая опция позволяет вызывать программы пакета гораздо короче и
удобнее.
Теперь не обязательно прописывать полные пути для внутренних
команд.
Можно указать каталог запуска и короткие относительные пути файлов.
Новая опция была использована чтобы сократить длину команд
клонирования проектов.
Это помогает избежать переполнения буфера интерпретатора при длинных
именах проектов.
Дело в том, что интерпретатор DaqPascal имеет
ограничение 255 на длину строки.
Указание относительных путей сокращает длину строки.
Плагины (дополнения, утилиты - называйте как хотите) для анализа данных ассоциируются с термином (именем) dan - от data analysis. Эта аббревиатура используется на кнопках, а также в именах файлов или каталогов.
Под анализом данных понимается обработка данных, заданных в окнах -
кривых.
Плагины анализа данных привязаны к окнам и применяются к кривым в данном
окне.
Был произведен перевод рабочих плагинов анализа данных из crw32. Их много, более 35. К счастью, все утилиты делались по одному шаблону, поэтому удалось автоматизировать этот процесс. Плагины были обработаны в пакетном режиме, в некоторых местах мелкие правки вносились вручную. Это позволило перевести плагины .dpr из crw32 в проекты .lpr в новой версии crwdaq менее чем за день (обработка файлов вручную заняла бы неделю).
Все плагины компилируются успешно.
Почти все переведенные плагины - рабочие. Во всяком случае, наиболее
часто используемые плагины (имена которых начинаются с подчеркивания
_) - проверены и работают.
Отдельные плагины (например, для построения гистограм) еще требуют добаботки, т.к. работают с файлами, имена которых зависят от операционной системы. Эти плагины будут доработаны в ближайшее время.
В настоящее время:
Проекты .lpr в пакете crwdaq делятся на три основные категории:
Плагины - загружаемые динамические
библиотеки, сделанные по специальным правилам.Консольные драйверы - консольные
программы, подключаемые по каналам к пакету в
daq-проектах.Консольные утилиты - консольные
программы разного назначения, используемые в
daq-проектах.В старой версии crw32 плагин соответствовал одному
файлу .dpr. Это было просто и удобно.
Однако в Lazarus или CodeTyphon
проекты занимают более одного файла - учитывая возросшую сложность
проектов.
Это, как минимум, головной файл .lpr, настройки проекта
.lpi и .lps, иконка
.ico, ресурсы .res.
Наличие этих файлов оправданно - там храняится пути поиска, ресурсы и
другие настройки проекта.
Поэтому приняты такие ПРАВИЛА:
Плагин с именем, например,
plugin_name, соответствует проекту
.lpr с таким же именем.program_name, соответствует проекту с тем
же именем./…/plugin_name,/…/plugin_name/plugin_name.lpr./…/plugin_name/plugin_name.*./…/plugin_name/plugin_name.lpi./…/plugin_name/plugin_name.dll./…/plugin_name/libplugin_name.so./…/program_name/program_name.exe./…/program_name/program_name._, считаются защищенными.В команду @view добавлена опция
@view activate ….
Эта команда активирует (вытаскивает наверх) окно.
Например:
@view activate Main Console # Активировать Главную Консоль
@view activate Главная Консоль # Активировать Главную Консоль
@view activate Заголовок Окна # Активировать окно по заголовкуФункционал плагинов обработки данных реализован практически в полном объеме. Реализовано выполение плагинов, редактирование, удаление, клонирование (создание из шаблонов). Программный код плагинов существенно переработан, улучшена структура, поправлены мелкие недостатки.
В текущем дистрибутиве crw32 есть около 40 плагинов
обработки данных.
В ближайшее время они будут переводится в новую версию
crwdaq.
Пока переведено 3 плагина.
В сценарии crwlazbuild добавлено сжатие файлов
командой strip.
Это уменьшает размеры исполняемых файлов за счет удаления отладочной
информации.
В сценарии crwlazclone сделана дополнительная
проверка, чтобы избежать ошибки попытки копирования проекта в самого
себя.
Такая ситуация может возникнуть, если неверно задать целевой каталог
(если он совпадает с каталогом исходного образца).
При этом выдается диагностика
“Ошибка: Источник = Приемник …”.
Продолжена работа над плагинами.
Добавлен файл _crw_plugin_abicall.inc
для правильного определения соглашений о вызове экспортируемой функции
плагина.
Windows использует StdCall,
Unix использует cdecl.
Соглашения вставляются с помощью
{$ _crw_plugin_abicall}.
Добавлен включаемый файл _crw_plugin_declare.inc
для выполнения правильного определения экспортируемой функции
плагина.
Декларация вставляются с помощью
{$ _crw_plugin_declare}.
Использование общего файла определения функции позволяет быть уверенным,
что все плагины будут декларировать экспортируюмую функцию плагина
одинаково.
Добавлен включаемый файл _crw_plugin_exports.inc
для выполнения правильного экспорта функции плагина.
Декларация вставляются с помощью
{$ _crw_plugin_exports}.
Использование общего файла определения функции позволяет быть уверенным,
что все плагины будут декларировать экспортируюмую функцию плагина
одинаково.
Все шаблоны плагинов переработаны с использованием этих включаемых файлов.
Доработаны модули поддержки плагинов.
Начата работа по переводу основных плагинов для расчетов dan = data analysis.
Продолжена работа над плагинами.
Пока удалось добиться частичной работы плагинов - в окне проекта
.lpr.
Но в принципе уже хорошо, что плагины хоть как-то заработали и
компилируются в среде пакета.
Для отладки плагинов сделан канал журналирования
_PluginWrap.
В нем будут отображаться события создания/уничтожения объектов - обёрток
для плагинов.
Специально для тестирования плагинов сделан шаблон проекта
test_plugin.dpr.
Существенно доработан модуль общей памяти _crw_sharemem.pas.
Доработки сделаны для корректной работы менеджера памяти в
плагинах.
Основой кода послужила одна хорошая статья,
взятая тут. Идея
состоит в том, что основной модуль crwdaq экспортирует
функцию GetMemoryManager, которая возвращает менеджер
памяти основного (исполняемого) модуля. Загружаемые плагины по условию
IsLibrary заменяют свой (текущий) менеджер памяти на
общий менеджер памяти основного (исполняемого) модуля
crwdaq. Таким образом, всё распределение памяти
делается средствами основного модуля. Поэтому все объекты (и строки),
созданные в плагине, остаются совместимыми с с адресным пространством
основного модуля.
После сборки FpcupDeluxe под Win64
выяснилось, что в коде библиотек crwlib и пакета
crwdaq есть мелкие несовместимости с
Win64.
Проблемы создавали в основном два вида несовместимостей:
Перегруженные (overload) функции, использующие тип
Extended.
Проблема связана с тем, что под Win64 тип
Extended совпадает с Double.
Поэтому перегруженные функции начинают дублироваться.
Проблема решается условной компиляцией
{$IFDEF SizeOf(Extended)<>SizeOf(Double)} … {$ENDIF}.
Некоторые функции WinApi, использующие тип
DWORD.
Проблема связана с тем, что под Win64 тип
DWORD иногда заменяется на
QWORD.
Проблема решается использованием типа PtrUInt.
После исправления код пакета стал компилироваться и запускаться на Win64 тоже.
Также при запуске пакета под Win64 сбоила (выдавала
исключение) функция GetMacAddress.
Она была доработана (заменена другой реализацией). В ходе доработки была
добавленв полезная команда
@list netifs.
В главную консоль добавлена команда (точнее опция)
@list netifs, которая печатает в консоль
список сетевых интерфейсов (list network interfaces).
Например:
@list netifs
eth0 28:d2:44:3b:9c:3b 192.168.0.11 255.255.255.0 INET+UP+BROADCAST+RUNNING+MULTICAST+LOWERUP
vboxnet0 0a:00:27:00:00:00 192.168.56.1 255.255.255.0 INET+UP+BROADCAST+RUNNING+MULTICAST+LOWERUP
Вывод в формате:
Интерфейс MacAddress IpAddress NetworkMask Flags+OptionsСоздана утилита
crwkit catlnk filename.lnk печатает
содержимое файла ярлыка Рабочего Стола.
Это файлы .lnk под Windows или
.desktop под Unix.
Написана на FreePascal.
Утилита работает в составе генератора проектов из шаблонов. Включена в состав пакета crwkit.
В библиотеку crwlib добавлена
функция AdaptLnkFileName(FileName). Эта
функция адаптирует имена файлов ярлыков для Рабочего
Стола под правила текущей операционной системы.
Напомним, файлы ярлыков для Рабочего Стола имеют
расширение .desktop под Unix или
.lnk под Windows.
Правила адаптации такие:
AdaptFileName(FileName).Таким образом, скорректированное имя ярлыка для Рабочего Стола будет соответствовать правилам текущей операционной системы.
Также в crwlib добавлена
функция ReadShellLinkAsText. Она читает содержимое
файла ярлыка для Рабочего Стола в виде текста,
состоящего из полей - строк вида Name=Value,
разделенных EOL.
Исполняемая команда содержится в поле с именем Exec.
Остальные поля зависят от системы. Под Windows доступны
поля Path, Arguments,
WorkingDirectory, ShowCmd,
IconLocation, Hotkey,
Description. Под Unix поля
соответствуют спецификации .desktop
файлов.
В DaqPascal эти функции пока доступны через вызов
paramstr(‘AdaptLnkFileName
…’) и paramstr(‘ReadShellLink
…’).
Возможно, позже они будут добавлены явно, как встроенные функции.
Обе добавленные функции потребовались для того, чтобы извлекать информацию о расположении компилятора FpcupDelixe из файлов ярлыков fpcupdeluxe .desktop/.lnk. Этот ярлык, сгенерированный при установке FpcupDeluxe и скопированный в папку ресурсов, служит для связки между пакетом crwdaq и компилятором FpcupDeluxe. Такой способ связки удобен - в случае изменения расположения компилятора достаточно просто скопировать другой файл ярлыка. Код менять не потребуется.
Для работы с компилятором FPC из Главной Консоли сделана команда @Fpcup:
@Fpcup # справка по команде
@Fpcup -help # вызов справки Lazarus
@Fpcup -busy # проверка - занят ли компилятор работой?
@Fpcup -check # проверка - компилятор FpcupDelux установлен?
@Fpcup -build ~/project.lpr # компиляция проекта (с указанием имени файла)При выполнении команды @fpcup -check
кроме печати также разрешается или запрещается команда вызова справки
Lazarus.
Также в стартовый сценарий пакета добавлена команда
fpcup_installed=@fpcup -check, благодаря
которой в переменной fpcup_installed после старта
содержится статус установки компилятора FpcupDeluxe
(0/1).
На этом тема интеграции пакета crwdaq с компилятором FPC пока закрыта.
Теперь можно быстро создавать программы FreePascal из шаблонов, редактировать и компилировать их прямо из среды пакета.
Дополнен сценарий входа под Windows - crwdaq.logon.cmd.
c:\opt\daqgroup\works для новых проектов
.lpr по образцу.c:\opt\crwlib,
c:\opt\crwkit,
c:\opt\crwdaq.Сценарий выполняется при входе в сеанс crwdaq.
Сделан сценарий клонирования (создания проекта по образцу) под Windows - crwlazclone.cmd.
Теперь команда Главного Меню
Файл/Создать/Новый Проект по Образцу
работает также под Windows.
В настоящее время сценарий клонирования (создания проекта по образцу)
работает на базе
crwlazclone.sh/crwlazclone.cmd.
В этих сценариях реализован минимальный набор функций - создание
целевого каталога, копирование файлов с заменой имени, замена имени
проекта на новое имя в основных файлах проекта (.lpr,
.lpi, .lps).
Некоторые проекты могут потребовать более сложных действий. Для этого предполагается создать программу с именем crwlazclone.lm9 на DieselPascal, которую можно вызывать из сценария crwlazclone.sh/.cmd. Сценарию передается имя образца .lpr, целевой каталог для проекта и новое имя проекта. Используя эту информацию, программа crwlazclone.lm9 может выполнять те или иные действия по созданию нового проекта. Эта программа будет наследовать окружение crwdaq, поэтому сможет получать и другую необходимую для работы информацию из переменных окружения. Создание этой утилиты не потребует изменения кода пакета, изменения коснутся только сценария crwlazclone.sh/.cmd. Поэтому эта программа полностью отдается на усмотрение Н.Гурину.
Инструмент для создания новых проектов .lpr по образцу в первом (грубом) приближении завершен.
Обнаружена проблема CHCP 65001 под
WindowsXP. Она заключается в том, что под
WindowsXP после выполнения команды
CHCP 65001 командный файл
.cmd молча “падает” и не выполняет никакой последующей
работы. Этой проблемы не наблюдается под Windows10, где
вроде бы всё работает нормально. Команда
CHCP 65001 устанавливает в консольной
программе кодировку UTF8 для ввода-вывода. Это
необходимо для новых программ под FreePascal, т.к. там
по умолчанию используется UTF8. Кодировка консоли
должна совпадать с кодировкой файлов, иначе возникают
“кракозябры”. Поскольку в начале проекта было решено
придерживаться (по мере возможности) универсальной кодировки
UTF8, все командные файлы сейчас заданы в этой
кодировке.
Пока эта проблема отмечена, но не решена, а отложена на будущее. Её решение потребует переработки большого числа командных сценариев .cmd, если всё-таки потребуется обеспечить совместимость с WindowsXP. Пока просто констатируем, что проблема есть.
Как пишут на форуме stackoverflow.com, это ошибка в коде WindowsXP:
The cause of this is when cmd.exe for windows xp internally call to the function MultiByteToWideChar using the argument dwFlags with the value 1. The documentation says this: “For UTF-8 dwFlags must be set to 0. Otherwise, the function fails”.
Намётки для решения (по тегу
consolesoft cmd_xp_65001_fix ): Обсуждение
consolesoft-mirror
patches.
Тестирование показало, что после установки заплатки
сценарии под WindowsXP с кодировкой
CHCP 65001 заработали. Но ещё требуется
тестирование.
Добавлен шаблон проекта daq_user_task.lpr.
Это шаблон консольного драйвера для crwdaq, т.е.
программу, которая подключается через канал к
DAQ-системе и может обрабатывать команды
@command …, как принято в пакете
crwdaq.
Шаблон содержит структуру для цикла опроса и минимальный набор команд для обработки. Взяв этот шаблон за основу, можно создавать свои консольные драйверы для прикладных задач.
В Главное Меню пакета crwdaq
добавлена новая команда: меню
Файл/Создать/Новый Проект по Образцу.
Эта команда вызывает диалог, позволяющий создавать новые проекты
Fpcup/Lazarus
из заранее подготовленных образцов (шаблонов). В диалоге можно:
В результате в целевом каталоге будет создана папка с новым
проектом.
Затем будет открыто текстовое окно для редактирования созданного
проекта.
В этом окне можно сразу редактировать, компилировать и запускать
программу.
Фактически создание проекта выполняет команда
crwlazclone.sh,
диалог просто подготавливает аргументы вызова для неё.
Разумеется, данный инструмент не ставит целью
заменить среду Lazarus.
С помощью этого инструмента будут создаваться специализированные
программы,
работающие в составе пакета crwdaq и прикладных
daq-систем.
Это, в первую очередь, консольные драйверы,
подключаемые к daq-системе
через каналы, а также плагины (загружаемые динамические
библиотеки).
Теперь есть инструмент для быстрой разработки таких прикладных
программ.
При создании шаблонов возникла проблема с указанием путей поиска
библиотек crwlib. Дело в том, что библиотеки
crwlib имеют фиксированный абсолютный
путь /opt/crwlib под Unix
или c:\opt\crwlib под
Windows. Документация Lazarus
рекомендует использовать относительные пути библиотек
при указании путей поиска в параметрах проекта. Дело в том, что
абсолютные пути плохо переносимы между платформами, т.к.
Windows использует имена дисков, а
Unix использует единое пространство имен файлов,
начиная с корня /.
Была найдена хитрость, с помощью которой удалось (с рядом оговорок)
задавать абсолютный путь переносимым образом. Для этого используется тот
факт, что для корневого каталога его родительским каталогом является он
же сам. Поэтому выражение
../../../../../../../../../../../../../../../../opt/crwlib
преобразуется в /opt/crwlib под
Unix или c:\opt\crwlib
под Windows, если только проект имеет глубину
вложенности (по подкаталогам) не более 16 от корневого
каталога. Под Windows также необходимо, чтобы проект
находился на том же диске, что и библиотека. Однако это приемлемая плата
за переносимость проектов между платформами.
Таким образом, в образцах (шаблонах) проектов используются пути
поиска типа
../../../../../../../../../../../../../../../../opt/crwlib
с множеством корневых каталогов. Не пугайтесь, это просто способ указать
абсолютный путь платформенно независимым способом.
Заложен механизм создания .lpr проектов
Lazarus из образцов (шаблонов).
Образцы проектов будут лежать в папке resource/sample. Каждый проект лежит в
одноименной папке, например,
resource/sample/lpr/demo/demo.lpr.
Файл crwdaq.sampl.ini будет содержать
список и описание шаблонов.
При добавлении очередного шаблона туда будут добавляться записи.
А механизм создания проектов будут общий. Это позволит в будущем легко
расширять набор образцов проектов по мере необходимости путем
конфигурирования, без изменения кода.
Сценарий crwlazclone.sh будет клонировать (создавать проекты из образцов - шаблонов). Ему передаются аргументы:
В настоящее время сценарий копирует файлы шаблона проект (с заменой имен файлов), а затем выполняет замену в файлах строк, содержащих имя проекта, на новое имя проекта.
Затем сценарий открывает окно для редактирования и компиляции .lpr проектов в crwdaq.
Сделана команда вызова Справка/Справка по Fpcup, которая вызывает справочную систему Fpcup/Lazarus.
В связи с выходом новой версии crw32 было выпполнено обновление тех функций, которые оказались затронуты в новой версии crw32.
Найдена и исправлена ошибка в реализации функций ReadIniVar, ReadIniStr. Ошибка заключалась в том, что функции извлекали не первое, а последнее вхождение (совпадение) имени параметра (или переменной), что отличало их поведение от функции readini. Функция readini прекращает поиск, как только находит первое совпадение имена параметра с заданным. А эти функции продолжали поиск до конца текста, хотя параметр уже найден. Теперь эта ошибка исправлена и все функции поиска/чтения параметров работают одинаково, т.е. возвращают первое найденное значение.
В стандартную библиотеку добавлена полезная функция общего назначения DupeString(s,n), которая n раз повторяет строку s. Эта функция может использоваться для манипуляции с повторяющимися строками, например:
msg:='@system '+DupeString('@async ',3)+'@run cmd';
// Результат: msg='@system @async @async @async @run cmd'Заметим, что для повторения символов лучше использовать StringOfChar(c,n), т.к. она работает быстрее.
Проведена доработка сервера &DimSrv.
Доработка связана со следующей проблемой, на которую обратил внимание Н.Гурин.
При разрыве связи или остановке DIM сервера,
DIM клиент каким-то образом должен получать уведомление
о том, что связь разорвана (событие NoLink - “нет
связи”). Это делается с помощью передачи клиенту некоторого сообщения от
сервера, которое в документации DIM называется
заполнителем (fill) или маркером
(mark). По замыслу, это такой набор данных, которого
не должно быть в нормальной передаче,
чтобы не перепутать обычные данные с маркером разрыва связи. Например,
если имееется целочисленный сервис DIM с форматом
I:1, в котором ожидаются неотрицательные целочисленные
данные, то можно использовать величину (-1) в качестве
маркера разрыва связи. Именно это значение - строка
dump(-1) - использовалось в прежней версии
DIM как маркер разрыва связи. И это обычно работало
неплохо. Тем более в случаях, когда размер сервисов отличается от
4 (т.е. размера типа Integer).
Проблема возникает, если требуется передавать в целочисленном сервисе любые значения, включая -1. В этом случае мы не можем отличить легальное (допустимое) значение передаваемых данных (-1) от маркера разрыва связи. В результате вместо передачи величины (-1), DIM клиент генерировал ошибку разрыва связи, а не принимал данные. Ситуацию можно было “вылечить” заданием заполнителя filling в описании сервиса, однако это не очень удобно и понятно, т.к. в таком случае нужно было задавать заполнитель filling в описании каждого (целочисленного) сервиса. Возможности задавать заполнителю значение по умолчанию не было.
Для решения описанной проблемы было предпринято следующее.
Было введено три параметра filling
(вместо одного):
заполнитель (NoLinkFill) - данные,
передаваемые в сервис при разрыве связи,
маркер (NoLinkMark) - данные, передаваемые от
сервера в качестве признака при разрыве связи,
обработчик (NoLinkHandler) - имя устройства,
которому посылается уведомление при разрыве связи.
Следует заметить, что обработчик не обязателен, т.к. ряд обязательных
действий при разрыве связи выполняет обработчик сервера
&DimSrv. Предполагается также, что маркер
выбирается так, чтобы он не мог возникнуть
в потоке нормальных данных, например, чтобы он отличался по размеру от
обычных данных. Кроме того, заполнитель передается только в случае, если
он отличается от маркера. Это позволяет отключить передачу заполнителя
(достаточно сделать его равным маркеру). Заполнитель и маркер задаются в
кодировке Base64.
Для справки, в файле dimsrv.cfg
стандартной конфигурации &DimSrv (используемой по
умолчанию) есть некоторые примеры заполнителей и маркеров.
В описании &DimSrv введены
параметры NoLinkFill,
NoLinkMark,
NoLinkHandler,
которые задают значение по умолчанию для заполнителя, маркера и имени
устройства-обработчика. Эти значения принимаются в случае, если в
описании сервиса параметр filling не указан. Значением
по умолчанию для заполнителя и маркера является
3-байтная строка ////,
соответствующая Hex(ffffff). Поскольку заполнитель по
умолчанию равен маркеру, он не передается в сервис.
Если передача нужна, надо задать заполнителю другое значение. Например,
можно использовать значение /////w==,
соответствующее Integer(-1)=Hex(ffffffff).
Проведена доработка сервера DimSrv в плане
улучшения журналирования. В код сервера добавлены дополнительные функции
для ведения журнала событий, где отображаются наиболее важные события
DIM: события пуска и завершения сервера, журнал ошибок,
подключение и отключение сервисов и клиентских компьютеров. События
журналируются в файл @dimevents.log с помощью
механизма команды @Integrity.
В описании &DimSrv введен
параметр DimLogMode,
который задает режим журналирования событий
DimSrv.
При подключении DIM сервиса (получении первого набора
данных сервиса) сделана посылка сообщения
@DimServiceUp … обработчику и серверу
&DimSrv, а также посылка команды
@integrity @DIM_INFO: @DimServiceUp … для
занесения в журнал событий DIM.
При отключении DIM сервиса (т.е. при разрыве связи)
сделана посылка сообщения @DimServiceDie …
обработчику и серверу &DimSrv, а также посылка
команды
@integrity @DIM_WARNING: @DimServiceDie …
для занесения в журнал событий DIM.
В библиотеке StdLibrary в стандартном
обработчике событий добавлены команды
@DimServiceUp … и
@DimServiceDie …. Стандартной реакцией
является печать сообщения в консоль устройства. Обработка сообщения
может быть перехвачена в прикладной программе, если нужна другая
обработка.
Примеры конфигурирования DimSrv с новыми параметрами:
[&DimSrv] ; Задать заполнитель/маркер/обработчик по умолчанию:
NoLinkMark = //// ; Использовать 3-байтный маркер разрыва связи $FFFFFF
NoLinkFill = /////w== ; При разрыве связи посылать в сервис Integer(-1)=$FFFFFFFF
NoLinkHandler = &Dimon ; Уведомлять устройство &Dimon о подключении/отключении всех сервисов
[]
[&DimSrv.ServiceList]
DIC_INFO:DDIM/CLOCK = dic_info DDIM/CLOCK
[DIC_INFO:DDIM/CLOCK]
tag DDIM.CLOCK
devPostMsg &DDIM.CTRL @DimTagUpdate=DDIM.CLOCK
filling T0ZG //// &DDIM.MAIN.CTRL
; Задает заполнитель "OFF", маркер разрыва связи $FFF
; и посылает уведомление устройству &DDIM.MAIN.CTRL
[]
Таким образом, в результате доработки сервер &DimSrv более корректно обрабатывает события разрыва связи, а также лучше их журналирует.
Добавлена ДЕМО конфигурация test_ddim от Н.Гурина. Эта конфигурация специльно создана для проверки проблемы с разрывом связи DIM сервера, описанная выше. Конфигурация очень проста, она добавлена для того, чтобы в будущем было легче проводить регрессионное (повторное) тестирование DIM сервера.
Обновлен Kirigami с мелкими правками от А.Жирунова.
Обновлен сценарий crwlazbuild.cmd. Там поправлена процедура извлечения командной строки из файла fpcupdeluxe.lnk.
В пакете crwdaq реализована компиляция проектов
Lazarus - программ .lpr.
Для компиляции используется сборка FpcupDeluxe,
подключенная с помощью сценариев
crwlazbuild.sh/crwlazbuild.cmd и
модуля _crw_fpcup.pas. В
этом модуле реализован объект Fpcup, управляющий
вызовом компиляторв и справки. Объект работает в стиле конечного
автомата, т.к. компиляция может занимать время. Реализовано также
текстовое окно form_lazarusprojecteditor.pas,
связанное с файлами проектов .lpr, которое умеет
компилировать проекты .lpr.
Сделанный редактор вполне достаточен для создания в среде пакета консольных драйверов, а также плагинов на базе загружаемых динамических библиотек, написанных на FPC/Lazarus.
В модуль _crw_str.pas добавилась
функция AdaptDllFileName.
Эта функция адаптирует имя файла динамически загружаемых библиотек -
.dll или .so.
Правила адаптации имени ENAME:
.dll.libname.so.В функцию paramstr введены подфункции AdaptFileName, AdaptExeFileName, AdaptDllFileName.
Это делает функцию AdaptDllFileName доступной в DaqPascal.
Сделана утилита crwlazbuild[.sh|.cmd].
Эта утилита компилирует проект FreePascal/Lazarus с помощью компилятора FPC из пакетной сборки FpcUpDeluxe, которая предполагается установленной в определенном (стандартном) месте. Это место определяется из ярлыка fpcupdeluxe.desktop или fpcupdeluxe.lnk, который создается при установке пакета (ярлык надо скопировать в папку resource). При отсутствии ярлыка берется значение по умолчанию.
Утилита принимает аргумент - полное имя файла проекта
projectname.lpr.
Например:
./crwlazbuild.sh /opt/suite/crwkit/add/src/pipeterm/pipeterm.lprВ результате в папке проекта собирается исполняемый файл, а также генерируетсяя журнал компиляции projectname_build.log.
По замыслу, утилита служит для компиляции проектов FreePascal/Lazarus из среды пакета crwdaq.
В набор утилит crwkit добавлена (но ещё не
завершена) группа утилит cherry (вишенка).
Она будет ассоциироваться со знаком вишни
.
По замыслу, это набор служебных утилит, доступных через команду
crwkit cherry … или
unix cherry …, например:
unix cherry firefox-backup # создать резервную копию настроек firefox
unix cherry show-ls-colors # показать таблицу цветов команды lsПока это (частично работающая) заготовка, которой (пока) можно пользоваться с большой осторожностью, т.к. она не завершена и не отлажена.
Группа утилит cherry добавлена сейчас, чтобы код не потерялся. Она будет дорабатываться в ближайшее время. О чём будет докладываться отдельно.
Сделана утилита crwkit fc-alias:
$ unix fc-alias list # Список псевдонимов для шрифтов
> monospace : NotoMono-Regular.ttf : Noto Mono : Regular
> sans : NotoSans-Regular.ttf : Noto Sans : Regular
> serif : PTAstraSerif-Regular.ttf : PT Astra Serif : Regular
> sans-serif : NotoSans-Regular.ttf : Noto Sans : Regular
> Arial : Arimo-Regular.ttf : Arimo : Regular
> Helvetica : n019003l.pfb : Nimbus Sans L : Regular
> Verdana : NotoSans-Regular.ttf : Noto Sans : Regular
> Times New Roman : PTAstraSerif-Regular.ttf : PT Astra Serif : Regular
> Courier New : Cousine-Regular.ttf : Cousine : Regular
$ unix fc-alias setup # Задает псевдоним для monospace = PT Mono
$ unix fc-alias remove # Удаляет ранее установленный псевдонимПсевдонимы фонтов - это специальные имена фонтов, такие как monospace, sans, serif, которые являются ссылками на реальные шрифты.
Утилита unix fc-alias list позволяет
узнать, какие реальные шрифты соответствуют известным псевдонимам.
Сделан сценарий textfileprint.sh/.cmd, выполняющий печать текста (на принтере). Имя принтера передается через переменную окружения PRINTER, а имя файла - в аргументе.
Под Linux сценарий использует команду
lpr fileName, а под
Windows -
notepad /PT "fileName" "printerName".
Через сценарий textfileprint теперь выполняется
печать текстовых окон. Содержимое окна (текст) копируется во временный
файл, который затем печатается и удаляется.
Таким образом, проблема печати в целом решена.
При запуске программы crwdaq переменная PRINTER (если она еще не установлена) устанавливается со значением текущего (активного) принтера (если он есть в системе).
После диалога выбора принтера (в программе crwdaq) переменная PRINTER также устанавливается в новое значение выбранного (активного) принтера.
Переменная PRINTER используется рядом программ
(например, командой печати lpr) при выводе
текста на печать для определения принтера (если он не указан в команде
явно). Это позволяет организовать печать текста на заданном принтере в
дочерних процессах.
Доработана (хотя не до конца) функция Файл/Печать в
текстовых окнах. Функция остается недоработанной в том смысле, что
печать TMemo делается в графическом режиме (изображение
видимой части текста в окне), а хотелось бы иметь печать самого текста.
Это можно сделать (на базе имеющегося кода), но требуется тщательная
проработка: разбиение текста на страницы, формирование изображения
страницы, печать изображения страниц и т.д. Сейчас код печати текста
локализован в модуле _crw_memo.pas, но
доработка кода отложена на время доработок после релиза (т.к. это
функция не первой необходимости).
Главная тема релиза - AdamWatchDogPulser. Ну и заодно несколько ДЕМО конфигураций.
Многие сценарии bash (обычно с расширением
.sh), входящие в пакеты crwkit и
crwdaq, содержат sudo …
для выполнения привилегированных команд.
По умолчанию команда sudo … является
интерактивной, т.е. запрашивает пароль при необходимости. Это может
создавать проблемы, если сценарий выполняется в пакетном режиме, либо
запускается как внешняя команда из среды пакета. Если команда будет
ожидать пароль, который никогда не поступит, то это может привести к
“зависанию” на ожидании завершения команды. И хотя вызов команд в пакете
обычно содержит ограничение по времени (таймаут), эта ситуация, которой
следует избегать.
По этой причине в сценариях .sh была произведена
массовая замена вызовов sudo … на
неинтерактивный вызов sudo -n ….
Неинтерактивный вызов sudo -n … работает
так же как обычный вызов sudo …, но при
необходимости ввода пароля он немедленно завершается с ошибкой. Таким
образом, если в данный момент вызов sudo без пароля
невозможен, то неинтерактивный вызов
sudo -n … не будет “висеть” в ожидании
ввода пароля, а немедленно завершится с ошибкой.
Указанная замена производилась исходя из предполагаемого целевого использования сценариев. Те сценарии, которые предназначены для интерактивной работы (в консоли), не затронуты. Правились те сценарии, которые вызываются как команды или работают в пакетном режиме. Изменения затронули более 30 сценариев (точно не считал).
Напомним, как работает sudo. В зависимости от
настроек /etc/sudoers, он может требовать или не
требовать пароль. При этом введенный пароль, при обычных настройках,
работает в течение некоторого времени аренды (обычно от
5 до 15 минут), в течение которых
пароль повторно вводить не нужно. Вызов
sudo -n -v продляет действие пароля еще на
один срок аренды.
Таким образом, вызов sudo -n … либо
успешно сработает, если пароль не требуется (либо по настройкам
sudo, либо по сроку аренды пароля), либо не будет
выполнен. Но никакого ожидания и “зависания” не будет.
Если sudo имеет настройки с паролем, достаточно
выполнить в консоли sudo -v, чтобы начать
или продлить аренду пароля. После этого в течение всего срока аренды
пароля вызовы sudo -n … будут срабатывать
успешно.
В Мониторе Ресурсов добавлены пункты Number of Threads (число потоков), а также Children Processes (число дочерних процессов).
Во время испытаний одной из установок Н.Гурин заметил, что в системе время от времени происходит ложное срабатывание сторожевого таймера WatchDog устройств ADAM.
По-видимому, это связано с работой алгоритма вычисления и сброса
WatchDog. При сбросе WatchDog алгоритм
использует значение 0.25*WatchDogTime в
цикле опроса команд для каждого устройства. Из-за сложности алгоритма
опроса (цикл по устройствам, для каждого устройства цикл по командам) и
задержки (сброс таймера делается в цикле опроса, когда подходит его
очередь) этого, видимо, оказывается недостаточно для надежного сброса
WatchDog. То есть команда сброса проходит слишком редко
и сторожевой таймер успевает сработать.
Для решения этой проблемы было решено ввести принудительный сброс WatchDog с постоянной частотой, независимой от значения WatchDogTime.
В устройства ADAM
добавлен параметр WatchDogPulser
или AdamWatchDogPulser.
Это период посылки команд (импульсов) сброса Watchdog в
миллисекундах. Параметр добавлен для улучшения работы сторожевого
таймера устройств ADAM. Также параметр [DAQ]
AdamWatchDogPulser задает общий для всех устройств
ADAM период импульсов сброса Watchdog.
В цикле опроса ADAM при вычислении периода импульсов
сброса используется минимальное значение из
WatchDogPulser, [DAQ]
AdamWatchDogPulser и величины
0.25*WatchDogTime.
Посмотрим, как это отразится на надежности работы сторожевого таймера.
Работа алгоритма Watchdog была проверена на
аппаратуре с конфигурацией i7017.cfg с
помощью консоли
@adam console; @adam debugmode 15.
Наблюдаемый период импульсов сброса Watchdog примерно
соответствует заданному (1000 ms), что позволяет сделать вывод о
корректной работе нового алгоритма сброса Watchdog.
Новая версия пакета работает в режиме SDI. Для управления окнами в SDI режиме создан специальный класс TSdiManager, имеющий единственный экземпляр - объект SdiMan. Этот объект инкапсулирует (включает в себя) большинство функций управления SDI окнами. До этого поддержка SDI режима была сделана в виде набора разрозненных функций. Их объединение в один класс упорядочивает код, делает его более ясным и модульным.
Введен параметр crwdaq.ini [System] CursorActivateMainSdiForm = crHelp, который задает курсор мыши для элементов, при двойном нажатии на которые активизируется Главное Окно программы.
Задание курсора CursorActivateMainSdiForm позволяет (по замыслу) сделать интерфейс более понятным - по курсору мыши видно, что можно делать с элементом.
Допустимые курсоры имеют примерно такой вид:
| Имя | Значение | Вид |
|---|---|---|
| crDefault | 0 | ![]() |
| crNone | -1 | ![]() |
| crArrow | -2 | ![]() |
| crCross | -3 | ![]() |
| crIBeam | -4 | ![]() |
| crSizeNESW | -6 | ![]() |
| crSizeNS | -7 | ![]() |
| crSizeNWSE | -8 | ![]() |
| crSizeWE | -9 | ![]() |
| crUpArrow | -10 | ![]() |
| crHourGlass | -11 | ![]() |
| crDrag | -12 | ![]() |
| crNoDrop | -13 | ![]() |
| crHSplit | -14 | ![]() |
| crVSplit | -15 | ![]() |
| crMultiDrag | -16 | ![]() |
| crSQLWait | -17 | ![]() |
| crNo | -18 | ![]() |
| crAppStart | -19 | ![]() |
| crHelp | -20 | ![]() |
| crHandPoint | -21 | ![]() |
| crSizeAll | -22 | ![]() |
| crSizeNW | -23 | ![]() |
| crSizeN | -24 | ![]() |
| crSizeNE | -25 | ![]() |
| crSizeW | -26 | ![]() |
| crSizeE | -27 | ![]() |
| crSizeSW | -28 | ![]() |
| crSizeS | -29 | ![]() |
| crSizeSE | -30 | ![]() |
Примечание:
Поскольку курсоры могуть настраиваться, в конкретной системе их внешний вид может отличаться от приведенного в таблице.
Объект TText переведен на длинные строки.
Раньше TText содержал динамический массив коротких строк, память выделялась под короткие строки специальными процедурами. Сильной стороной была потоковая безопасность, однако короткие строки ограничивали применимость TText.
Теперь TText серьезно переработан и теперь является фактически потокобезопасной “оберткой” для TStringList, то есть внутри (в private данных) текст хранится в виде объекта TStringList. Программная “обертка” обеспечивает потоковую безопасность и защиту от сбоев.
Напомним, что TText является потокобезопасной и высоко защищенной версией объекта “текст”. Он безопасен как в смысле потоков (все методы защищены Lock/Unlock), так и в смысле исключений и доступа (защита от нулевого указателя, защита от неверной индексации и т.д.). Поскольку объект обложен всеми ввозможными “подушками безопасности”, он работает немного медленнее, чем просто TStringList, однако его использование (особенно в DaqPascal) оправдано поввышением безопасности и отказоустойчивости работы программ. Объект TText целесообразно использовать в тех случаях, когда работа идет в многопоточной среде и когда требуется повышенная защита от программных сбоев.
Переход к длинным строкам почти завершен, теперь осталось совсем немного мест, где остаются короткие строки. В основном они связаны с чтением конфигурационных файлов.
В окнах мнемосхем по двойному щелчку на свободном поле мнемосхемы (то есть там где нет сенсоров) тоже сделан вызов Главного Окна программы.
Таким образом, теперь можно вытащить Главное Окно crwdaq наверх двойным кликом на Строке Статуса, а также на Панели Инструментов в любом (немодальном) окне пакета, а также на пустом поле любой мнемосхемы.
Сделаны исправления в DAQ - устройстве типа Device Software Dialog. После перехода под FreePascal геометрия диалога нарушилась, а некоторые элементы отображались неверно. Из-за этого диалог хотя и работал, но выглядел довольно странно, с искажением геометрии и внешнего вида.
Внесенные изменения исправили ситуацию. Теперь диалог отображается максимально близко к тому, как он выглядел в старой верии crw32.
При переходе к SDI интерфейсу появилась проблема,
которой в MDI не было.
А именно, Главная Форма (где расположено Главное Меню и
Панель Инструментов) может быть “спрятана” под другими
окнами.
Нужен способ быстро её “достать”, переместить “наверх”, чтобы её было
видно на экране.
Для решение этой задачи была сделана активизация Главного Окна по двойному нажатию Строки Статуса, т.е. DoubleClick on StatusBar в любом “дочернем” окне.
Кроме того, аналогичное действие двойному нажатию кнопки мыши сделано на Панели Инструментов (точнее, на свободном от кнопок пространстве Панели Инструментов), а также на свободном пространстве консольных окон (там где надписи Input, Output).
Таким образом, теперь можно вытащить Главное Окно crwdaq наверх двойным кликом на Строке Статуса, а также на Панели Инструментов в любом (немодальном) окне пакета.
Внесены дополнительные исправления в форматирование
Format('%g',…).
Как было обнаружено, кроме формата %g в
коде присутствуют сопутствующие форматы вида
'%12g',
'%-12g',
'%*g',
'%-*g' и им подобные. Такие форматы
сделанный ранее алгоритм коррекции не учитывал и не корректировал.
Поэтому из-за неверного форматирования (с избыточной точностью),
например, “ломались” таблицы в диалоге калибровки, рассчитанные на
корректную работу функции форматирования.
Алгоритм коррекции формата '%g' был
дополнен указанными выше случаями.
После исправления таблицы в диалоге калибровки стали отображаться
корректно.
Продолжена работа по постепенному уходу от коротких строк ShortString в пользу LongString. Введен тип PureString - как синоним ShortString для “чистого” кода. Он используется в тех местах, где использование ShortString выглядит обоснованным. Например, там где длинных строк возникнуть не может или в записях, где байтовый размер строк важен. Указание типа PureString означает, что в этом месте использование коротких строк обоснованно и вряд ли будет изменено на длинные строки.
Хотя все сделанные изменения довольно мелкие, они “рассыпаны” по всему коду, и это проблема. Изменения, касающиеся замены коротких строк на длинные, затронули более 50 модулей программы. Будем надеяться, что ничего не поломалось. При тестовых запусках проблем пока не было обнаружено.
В DaqScript, а также в DaqPascal добавлена константа CpuBitness. Это разрядность процессора - число бит в указателе Pointer, бывает 32/64.
В DaqScript, а также в crwlib
добавлена функция LeastPowerOfTwo(x). Она определяется
как
наименьшая степень двух, которая больше или равна x,
т.е. min(2^N>=x).
Например:
LeastPowerOfTwo(1) = 1
LeastPowerOfTwo(2) = 2
LeastPowerOfTwo(3) = 4
LeastPowerOfTwo(4) = 4
LeastPowerOfTwo(5) = 8
LeastPowerOfTwo(6) = 8
LeastPowerOfTwo(7) = 8
LeastPowerOfTwo(8) = 8Функцию LeastPowerOfTwo удобно, например, использовать для вычисления размера буферов динамических структур.
Во всех demo конфигурациях кроме demo_fast_poll частота
опроса потоков ограничена значением 4 ms,
то есть параметр DevicePolling = 1, …
заменен на DevicePolling = 4, ….
Выбор 4 ms не случаен. Это, с одной стороны, квант времени msecnow под Linux, с другой стороны это достаточно быстрый опрос, частоты которого обычно должно хватать для работы.
Рекомендуется выбирать период опроса
DevicePollingне менее4 ms, кроме особых случаев, где выбор более частого периода (1…3) действительно необходим. Это поможет избежать необоснованно высокой загрузки процессора под обеими системами Linux/Windows.
Поскольку новая версия пакета сделана в стиле SDI (Single Document Interface), возникала потребность доработать элементы SDI интерфейса.
В первую очередь это касается меню. В старой версии пакета
(crw32) меню окон работало по правилам
MDI (Multi Document Interface). Правила
состояли в том, что элементы меню дочерних MDI окон
объединялось (Merge) с пунктами меню главного окна и
отображалось в главном меню, а не в меню дочернего окна. При этом
содержимое меню главного окна менялось в зависимости от того, какое
дочернее окно в данный момент активно. Это позволяло экономить место на
экране и избегать избыточного дублирования функций меню главного окна и
дочернего окна, сосредоточив весь функционал в главном меню. Назовем
такое поведение объединением меню -
Menu Merge.
Задача состоит в том, чтобы воспроизвести такое же поведение меню в SDI окнах. Проблема состоит в корректном объединении главного меню и меню дочерних окон.
Для решения этой задачи было введено два параметра:
EnableSdiFormMenuMerge = 1 -
разрешает объединение меню дочерних SDI форм с главным
меню
HideChildSdiFormMenu = 1 - прячет
меню дочерних SDI форм при объединении с главным
меню
Эти параметры системно зависимы и помещены в разные секции - [System:Unix] и [System:Windows]. Они позволяют управлять объединением меню дочерних SDI форм с главным меню.
В процессе изучения вопроса было выяснено, что на объединение меню влияет два параметра: MenuItem.Caption и MenuItem.GroupIndex. В случае Windows всё работает довольно понятным образом: меню с одинаковым текстом и индексом объединяются, при этом пункт меню дочернего окна замещает соответствующий пункт главного меню. В случае Linux/GTK работа алгоритма объедиения меню пока осталась непонятной.
По результатам работы удалось корректно реализовать объединение меню
в версии Windows.
К сожалению, под Linux объединение меню пока не
работает. Будем решать проблему дальше.
Изменения в функциях filerename, filecopy.
Эти функции принимают пару имен файлов в виде одной строки
s = Источник Приемник.
Поскольку имена файлов могут содержать пробелы, они передавались в
URL кодировке.
Например:
FileCopy(URL_Encode(Source)+' '+URL_Encode(Target))
Это не всегда удобно и понятно.
Теперь передача параметров может идти тремя путями:
Имена файлов (исходные) с разделителем
EOL.
Признаком служит наличие маркера EOL в строке.
Например:
FileCopy(Source+EOL+Target)
Имена файлов в “кавычках” с разделителем - пробелом.
Признаком служит наличие кавычек в строке.
Например:
FileCopy(AnsiQuotedStr(Source,QuoteMark)+' '+AnsiQuotedStr(Target,QuoteMark))
Имена файлов в URL кодировке с разделителем -
пробелом.
Признаком служит отсутствие в строке кавычек и маркера
EOL.
Например:
FileCopy(URL_Encode(Source)+' '+URL_Encode(Target))
Первый вариант (с EOL) удобен своей
краткостью.
Но он не работает в случае посылки команд по линии связи.
Ведь маркер EOL служит также для разделения команд.
Второй вариант (с кавычками) рекомендуется как наиболее
распространенный и понятный.
Надо лишь не забывать всегда помещать имена файлов в кавычки (даже если
нет пробелов).
Третий вариант (с URL кодировкой) оставлен для совместимости.
В компиляторе DaqPascal проделана большая работа: все строки переведены с коротких строк на длинные строки. Это значит, что теперь сняты ограничения на длину строк в 255 символов, которые существовали для целого ряда функций DaqPascal (особенно для старых, давно разработанных функций). Документацию пока поправить не успел.
При этом остаются следующие ограничения на длину строк:
Длина всех строк DaqPascal ограничена длиной Compiler.slenmax, которую можно менять в секции [compiler.options]. По умолчанию это около 2 МБ - достаточно для обычных задач.
Некоторые функции (например, readini) имеют внутреннее ограничение в 255 символов на длину читаемых из конфигурации строк, что связано с размерами внутреннего буфера для чтения данных. Также ограничения в 255 символов имеет функция voice и ряд других. В практике не было случаев, когда эти ограничения создавали бы проблемы.
Длина строк в текстах (см. text_new) пока имеет ограничение в 255 символов. Это ограничение, вероятно, будет снято в будущем.
Все остальные функции теперь имеют максимальную длину строк, ограниченную только параметром Compiler.slenmax и объемом доступной памяти.
Была обнаружена проблема с форматированием
Format('%g',[…]), которое используется в
пакете как основной формат для вещественных чисел. Дело в том, что очень
широко используемый формат ‘%g’ в
FreePascal интерпретируется как формат
‘%.17g’ - с расчетом на чила типа
Extended, в то время как в Delphi
используется формат ‘%.15g’ - с расчетом на числа типа
Double.
Из-за этого, например, число печатается с избыточным числом знаков
0.1 // исходное число
0.10000000000000001 // число на печатиДля устранения этой проблемы функция Format модифицирует формат ‘%g’ в явный формат ‘%.15g’. Другими словами, выполняет коррекцию формата. Это происходит “прозрачно” для прикладного кода, на уровне кода библиотек.
Для управления поведением функции Format введен параметр crwdaq.ini [System] UsesFixFormatG = 1. При его отключении коррекция формата не производится.
Переведена демо конфигурация demo_lincorr. Используется для сглаживания и дифференцирования зашумленного сигнала в реальном времени. Имеется справка.
Переведена демо конфигурация demo_lakeshore. Это драйвер для контроллера температурной стабилизации LAKESHORE. Имеется справка.
Переведена демо конфигурация demo_ec3x32. Это драйвер для контроллера ТРВ (терморегулирующего вентиля) EC3-X32. Имеется справка.
В рамках подготовки к релизу в модулях проводилась массовая замена коротких строк (ShortString) на длинные строки (LongString). Короткие строки достались в наследство от старых версий Pascal, они имеют ограничение (255) по длине и в ряде случаев работают медленнее, чем длинные строки (хотя в ряде других случаев это не так). Так или иначе, длинные строки в новых версиях Pascal являются основным и доминирующим строковым типом. Проводимые замены призваны постепенно избавиться от коротких строк или по крайней мере ограничить их использование необходимым минимумом - там, где они оправданы.
Пока короткие строки полностью вытеснить длинными не удалось, да это и не требуется, Однако число использования коротких строк изрядно сократилось. И будет сокращаться по мере подготовки релиза.
Среда разработки Lazarus, в отличие от старого Delphi5, содержит довольно развитый анализатор кода, который выдает по мере компиляции сообщения разных типов (разного уровня серьезности):
errors - ошибки компиляции. Генерация кода программы прекращается.
warning - предупреждения. Генерация кода программы продолжается, но наличие предупреждения говорит о серьезной проблеме в коде. На практике большинство предупреждений в коде пакета действительно указывали на ошибки либо ситуации, с большой вероятностью приводящие к ошибке времени исполнения.
hints - замечания. Генерация кода программы продолжается, но наличие предупреждения говорит о наличии проблеммного, потенциально ошибочного кода. Это не обязательно ошибка, но компилятор не может определить, корректен ли код.
При разработке пакета crwdaq было решено придерживаться “нулевой толерантности” к предупреждениям и замечаниям компилятора. В настоящее время при компиляции пакета нет предупреждений - они все были устранены доработкой кода. Но замечания были. Они устраняются по мере сил.
Некоторые замечания не очень серьезны с точки зрения надежности кода. Например, замечания типа “эта переменная объявлена, но не используется” указывает на “мусорный” код, когда какой-то код удаляется или редактируется, а неиспользованные переменные забыли удалить из объявлений. Такие замечания легко исправляются, к тому же они не несут угрозы надежности программы.
Другие замечания указывают на наличие довольно серьезных проблем с кодом. Например, замечания типа “переменная используется, но не инициализирована указывают на то, что где-то забыли присвоить переменной начальное значение. Типичный пример такого кода:
procedure ProcessData(var x:Real);
begin
... какой-то код обработки ...
end;
procedure Processing;
var x:real;
begin
while not Terminated do begin
ProcessData(x);
writeln(x)
end;
end;В этом коде есть проблема - начальное значение переменной
x при первом вызове процедуры
ProcessData не определено. Возможно, что это и не
ошибка - значение переменной x может вычисляться внутри
процедуры и возвращаться как результат. Однако в общем случае это
ошибка. Внутри процедуры ProcessData переменная
x может быть использована как переданное значение.
Например, если ProcessData содержит код
procedure ProcessData(var x:real); begin x:=x+1; end;,
то значение x на выходе будет иметь неопределеное
(“мусорное”) значение. Потенциально это ошибка времени исполнения любого
уровня серьезности. Это особенно “вредная” ошибка потому что мусорные
значения переменных приводят к непредсказуемому поведению программы (то
работает, то нет).
Замечания этого типа легко устраняются иницилизацией переменной где-то в начале блока кода, до её первого использования:
procedure ProcessData(var x:Real);
begin
... какой-то код обработки ...
end;
procedure Processing;
var x:real;
begin
x:=0; // инициализация
while not Terminated do begin
ProcessData(x);
writeln(x)
end;
end;Теперь код корректен (верен) с точки зрения компилятора. Независимо от того, что делает или не делает процедура ProcessData, поведение программы будет, как минимум, предсказуемым (детерминированным), выдавая одни и те же результаты в одинаковых условиях.
В компиляторе DaqPascal после перевода под FreePascal было обнаружено более 10 замечаний такого типа (переменная не инициализирована). Это не обязательно значит, что там есть ошибка. Но предпосылки для ошибок были. Компилятор - сложный код, отследить все “ветки” алгоритмов тяжело. Поэтому была проведена большая работа по устранению всех замечаний такого типа. Для этого использовался гарантированно безопасный метод - значение проблемных переменных инициализировалось (обычно нулем) сразу после begin того блока, в котором переменная была объявлена (как в приведенном примере). Это гарантирует, что переменная получает разумное начальное значение до любого её использования.
В результате сейчас код компилятора DaqPascal компилируется без замечаний. Все потенциальные проблемы указанного типа устранены.
Посмотрим, как это отразится на работе прикладных программ.
Проведена доработка библиотеки
_crw_lcard.pas и утилиты
lsldev. Теперь они работают под
Linux и Windows.
Проведена доработка утилиты lsldev. Теперь кроме списка устройств она умеет считывать параметры для заданных устройств.
Примеры:
# Чтение списка устройств LCARD:
unix lsldev
#DEV SLOT PATHNAME STATUS TYPE:NAME BOARD_NAME REV SERIAL_NUMBER
1 0 /dev/ldev0 0:SUCCESS 31:E140 E140 B 1D699929
1 LCARD device(s) found.
# Чтение параметров виртуального слота 0:
unix lsldev /dev/ldev0 # или просто: unix lsldev 0
Information on LCARD Virtual Slot[0]:
Slot: 0
Device.Link: /dev/ldev0
Device.Path: /dev/ldevice0
Slot.Base: 0x0
Slot.BaseL: 0
Slot.Mem: 0
Slot.MemL: 0
Slot.BoardType: 31:E140
Slot.DSPType: 0
Slot.Irq: 0
Plata.Test: 0:SUCCESS
Plata.BrdName: E140
Plata.Rev: B
Plata.SerNum: 1D699929
Plata.Quartz: 16000000
Plata.IsDacPresent: 1
Plata.CRC: -1
Plata.KoefADC: 0.3722697, 1.576326, 8.805132, 37.39174, 1.010523, 1.004837, 1.001025, 1.000101
Plata.KoefDAC: 4.246524, 4.009336, 0.9802795, 0.9829721
Plata.Custom: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Plata.CustomHex: 00000000000000000000000000000000000000000000000000000000000000000000000000000000Примечания:
Работа утилиты lsldev проверена под
AstraLinux.
Утилита lsldev компилируется, но (пока) не работает под
Windows.
Она будет доработана позже, чтобы не задерживать разработку пакета
сейчас.
Драйвер для сбора данных под crwdaq также будет сделан
позже.
Сейчас достаточно того, что есть работающие драйверы и
API.
В папке /opt/daqgroup/share/lcard
есть документация и примеры,
а также драйверы под Windows и
AstraLinux.
В модуле _crw_lcard.pas сделана автоматическая загрузка драйверов ядра LKernelModulesLoad в фабрике интерфейсов LCreateInstance. Это позволяет не заботиться о проблеме загрузки драйверов ядра. Всё будет делаться автоматически. Это удобно.
Для загрузки используется команда
sudo -n unix ldev-cpl start.
Сделана и добавлена в пакет crwkit утилита
unix lsldev или её синоним
unix lslcard. Эта утилита показывает
список подключенных устройств LCARD с типами и
серийными номерами. Это удобная для практики утилита на будущее. В
настоящее время её польза cjcnjbn в том, что она тестирует
работоспособность драйверов и библиотек LCARD. Создание
драйверов LCARD для crwdaq теперь
возможно, но пока откладывается (до выхода первого релиза).
Пакет daqgroup-lcard был модифицирован и пересобран.
Причина в том, что в файле
interface/stubs.h потребовалось заменить
определение:
// определение
#define __stdcall
//заменено на определение
#define __stdcall __attribute__((cdecl))Причина в том, что интерфейсы (interface) используют
соглашение о вызовах функций stdcall под
Windows или cdecl под
Unix.
Исходная версия библиотеки под Linux использовала
пустое определение __stdcall, что по факту
означало соглашения о вызовах C++, а не
C. Чтобы интерфейсы работали корректно,
требуется определить __stdcall как
cdecl.
Также была добавлена команда
/opt/daqgroup/share/lcard/linux/ldev-cpl
для управления драйверами:
/opt/daqgroup/share/lcard/linux/ldev-cpl start # загрузить драйверы ldev*.ko в ядро
/opt/daqgroup/share/lcard/linux/ldev-cpl restart # перезагрузить драйверы ldev в ядро
/opt/daqgroup/share/lcard/linux/ldev-cpl stop # удалить драйверы ldev*.ko из ядра
/opt/daqgroup/share/lcard/linux/ldev-cpl status # проверить загружены ли драйверы ядраЭта команда позволит управлять загрузкой драйверов LCARD.
В сборку crwkit добавлена команда
unix ldev-cpl или её синоним
unix lcard-cpl.
unix ldev-cpl start # загрузить драйверы ldev*.ko в ядро
unix ldev-cpl restart # перезагрузить драйверы ldev в ядро
unix ldev-cpl stop # удалить драйверы ldev*.ko из ядра
unix ldev-cpl status # проверить загружены ли драйверы ядра
Эта команда позволит более удобно управлять
загрузкой драйверов LCARD.
Удобство в том, что не надо заботиться о (длинных) путях.
Вызов идет через общий механизм crwkit.
Команду unix ldev-cpl можно также
вызывать в программах Pascal (как внешнюю команду) для
управления драйверами LCARD.
Создан модуль _crw_lcard.pas для работы с устройствами LCARD для PCI: L761, L780, L783, L791; для USB: E14-140(M), E14-440, E20-10, E154.
Интерфейсный модуль был взят из примеров от LCARD на Delphi, но его пришлось серьезно переработать, с использованием интерфейсов (interface), т.к. примеры были под очень старый Delphi, несовместимый с FPC, к тому же только под Windows. Пришлось изрядно повозиться, особенно с проблемой stdcall/cdecl. Но в конце концов все заработало.
Модуль проверялся в программе crwtestbench. Как минимум, правильно работают: загрузка библиотеки, фабрика интерфейсов, функции чтения параметров слота USB и параметров подключенного устройства - проверялось на E14-140.
Разумеется, это пока только библиотека API. Драйверы для crwdaq еще предстоит создать.
Создан deb пакет daqgroup-lcard, содержащий драйверы LCard, включая E14-140, E14-440 и другие устройства. Этот пакет не включен в install-daqgroup-all.run, т.к. драйверы LCARD нужны не всегда. Поэтому его надо устанавливать/обновлять вручную.
Удаление пакета делается командой
sudo apt remove daqgroup-lcard.
Пакет распаковывает в /opt/daqgroup/share/lcard
драйверы ядра, библиотеки, заголовочные файлы, справочные файлы, примеры
и другие нужные для разработки файлы. Также он делает доступной для всех
прикладных программ библиотеку liblcomp.so,
нужную для программного доступа к устройствам LCARD.
Это обеспечивается с помощью файла /etc/ld.so.conf.d/daqgroup-lcard.conf,
указывающего на каталог /opt/daqgroup/share/lcard/linux,
где лежит библиотека. Команда
sudo ldconfig обновляет базу данных
библиотек, после чего вызов
LoadLibrary('liblcomp.so') находит
библиотеку из любого места.
Также пакет устанавливает udev правила lcard.rules, чтобы
устройства lcard автоматически подключались к системе
при подключении разъема USB. Система
udev создает ссылки
/dev/ldev0 …
/dev/ldev0 для доступа к устройствам из
пользовательского режима.
Также пакет daqgroup-lcard
устанавливает и загружает в ядро драйверы, т.е. модули
ядра: ldevpci,
ldevusb,
ldevpcibm,
ldevice.
Список загруженных модулей ядра можно увидеть командой
lsmod или
cat /proc/modules. При установке модулей
ядра также создаются устройства
/dev/ldevice0 …
/dev/ldevice7.
При установке пакета делаются записи в журнал /tmp/dpkg-daqgroup-lcard.log.
В состав пакета входит тестовая программа test, которая должна проверять работу драйвера и библиотек. В настоящее время пакет проверен лишь частично, т.к. для полной проверки требуется разработать библиотеки под FreePascal и драйвер для crwdaq. Сейчас можно лишь сказать, что драйвер и библиотеки как-то работают (подключаются, определют тип устройства и его параметры, считывают какие-то данные из устройства). Работы по созданию драйвера LCard для crwdaq будет продолжена.
Все найденные аналоги буферов для строк с именами файлов типа
array[0..MAX_PATH-1] of char заменены
типом TMaxPathBuffer.
Следует избегать явного определения типов в коде, предпочитая
использовать библиотечные типы. Это делает код более однородным, ясным и
управляемым.
Функция ScanVar является основной функцией чтения параметров по заданному формату из буферов памяти или (после загрузки буфера) из конфигурационных файлов. Её недостатком является то, что она работает с нетипизированной записью - буфером для параметров. Это оправдано, когда читаемые данные имеют сложную структуру - например, запись record. Однако наиболее частый случай - чтение простых типов данных. Для них целесообразно использовать типизированные переменные, чтобы работал контроль типов на уровне компилятора. Для этого добавлены функции:
ScanVarBoolean - чтение переменной типа Boolean
ScanVarInteger - чтение переменной типа Integer
ScanVarLongInt - чтение переменной типа LongInt
ScanVarDouble - чтение переменной типа Double
ScanVarWord - чтение переменной типа Word
ScanVarAlpha - чтение переменной типа String - только первое слово
ScanVarString - чтение переменной типа String - вся строка
ScanVarRecord - чтение записи, эквивалентно ReadIniFileVariable,
функция добавлена для улучшения читабельностиЗатем производилась массовая замена ScanVar на приведенные выше функции для чтения типизированных данных. Это позволило резко сократить число нетипизированных вызовов. Оставшиеся нетипизированные вызовы для сложных структур заменялись на вызовы ScanVarRecord для повышения читабельности кода.
Предпринятые меры призваны повысить безопасность и надежность кода, т.к. значительная часть потенциальных ошибок отсекается на этапе компиляции.
Функция ReadIniFileVariable является основной функцией чтения параметров из конфигурационных файлов .ini, .cfg, .crc, .cal. Её недостатком является то, что она работает с нетипизированной записью - буфером данных. Это оправдано, когда данные имеют сложную структуру - например, запись record. Однако наиболее частый случай - чтение простых типов данных. Для них целесообразно использовать типизированные переменные, чтобы работал контроль типов на уровне компилятора. Для этого добавлены функции:
ReadIniFileBoolean - чтение переменной типа Boolean
ReadIniFileInteger - чтение переменной типа Integer
ReadIniFileLongInt - чтение переменной типа LongInt
ReadIniFileDouble - чтение переменной типа Double
ReadIniFileWord - чтение переменной типа Word
ReadIniFileAlpha - чтение переменной типа String - только первое слово
ReadIniFileString - чтение переменной типа String - вся строка
ReadIniFileRecord - чтение записи, эквивалентно ReadIniFileVariable,
функция добавлена для улучшения читабельностиЗатем производилась массовая замена ReadIniFileVariable на приведенные выше функции для чтения типизированных данных. Это позволило резко сократить число нетипизированных вызовов. Оставшиеся нетипизированные вызовы для сложных структур заменялись на вызовы ReadIniFileRecord для повышения читабельности кода.
Предпринятые меры призваны повысить безопасность и надежность кода, т.к. значительная часть потенциальных ошибок отсекается на этапе компиляции.
В целях повышения безопасности кода все найденные в коде пакета вызовы функций StrPCopy, StrCopy заменены на более безопасные вызовы функций StrPLCopy, StrLCopy. Эти безопасные функции контролируют размеры буферов при работе с строками в стиле C (массив символов, который заканчивается нулем). Безопасные функции обеспечивают корректную работу со строками, размеры которых превышают размеры буфера и предохраняют от фатальных ошибок типа переполнение буфера.
Также все найденные аналоги буферов для анализа (парсинга) строк типа
array[byte] of char или
array[0..255] of char заменены типом
TParsingBuffer. Это
делает код более однородным, ясным и управляемым.
Проводились доработки службы сторожевого таймера
WatchDog и службы системного времени
Mistiming. Доработки касались оптимизации
и всплывающих уведомлений при обнаружении проблем.
Добавлены параметры crwdaq.ini:
MistimingUseTooltip = 1 - Использовать
всплывающие уведомления Службы Системного Времени при
рассинхронизации часовMistimingCmdOpen = resource\shell\crwdaqopenmistiming.cmd
- задает сценарий обработки нажатия всплывающего уведомленияWatchDogUseTooltip = 1 - Использовать
всплывающие уведомления при срабатывании Сторожевого
ТаймераWatchDogCmdOpen = resource\shell\crwdaqopenwatchdog.cmd
- задает сценарий обработки нажатия всплывающего уведомленияИспользование всплывающего уведомления позволяет сделать уведомления службы сторожевого таймера и системного времени менее навязчивыми, чтобы они не мешали обычной работе программы. Реакция на нажатие кнопки всплывающего уведомления позволяет открыть окно сторожевого таймера или службы системного времени для получения более подробной информации.
Обновлены пакеты daqgroup-dim до версии 20.37-1astra3, daqgroup-smi до версии 58.01-1astra2. Изменения небольшие, также связанные с realpath.
Переведена на новую версию пакета демо-конфигурация - demo_wika.
Это драйвер датчиков давления Wika на шине
RS-232 c полноценным симулятором и генератором.
Работает под Unix и Windows.
В сценариях bash произведена массовая замена
# вызов
readlink -f …
# заменен на
realpath …
# группа операторов
readonly scripthome="$(readlink -f $(dirname $scriptfile))";
readonly scriptFILE="$(readlink -f $scriptfile)";
readonly scriptHOME="$(readlink -f $(dirname $scriptFILE))";
# заменена на
readonly scripthome="$(dirname $scriptfile)";
readonly scriptFILE="$(realpath $scriptfile)";
readonly scriptHOME="$(dirname $scriptFILE)";Вроде бы новый код быстрее, точнее и понятнее. Как пишет документация GNU coreutils:
The file name canonicalization functionality overlaps with that of the readlink command. This is the preferred command for canonicalization as it’s a more suitable and standard name. In addition this command supports relative file name processing functionality.
То есть realpath - это предпочтительная команда для вычисления имен файлов. Так что изменения сделаны в рамках рекомендаций GNU.
Но надо быть внимательнее - вдруг при замене закрались ошибки. Ведь изменения коснулись более 200 файлов (сценариев).
В главном окне пакета cradaq включены всплывающие подсказки - свойства Hint, ShowHint.
Доработана подсистема WatchDog -
сторожевой таймер. Там некорректно
работали всплывающие уведомления под Unix - теперь это
исправлено. Кроме того, добавлена закладка Журнал/Log
для просмотра журнала сторожевого таймера.
Доводился до ума диалог SelectDirectoryDialog. Работа шла вокруг проблемы (правильного) позиционирования на экране и заголовка. Вроде бы сейчас всё работает верно в обеих системах Linux и Windows.
По аналогии с защитой таймеров, сделана защита от избыточных рекурсий при обработке сообщений. Все найденные в коде пакета вызовы Application.ProcessMessages заменены вызовами SafeApplicationProcessMessages, в котором стоит защита от рекурсий. Параметр crwdaq.ini [System] MaxAppProcMessagesLevel = 10 задает максимальный уровень рекурсии. Уровень 10 выбран как разумный уровень, который с одной стороны допускает рекурсию (которая нужна, например, в модальных диалогах), а с другой стороны надежно защищает от рекурсивой петли.
В функции edit добавлен диалог SelectDirectoryDialog. Этот диалог служит для выбора существующего или создания нового каталога на диске.
Сделана группа функций разбора слов и фраз:
Фразы отличаются от слов тем, что фразы могут помещаться в кавычки. Внутри кавычек допускаются пробелы, которых в словах не допускается.
Новый набор функций расширяет возможности обработки строк.
Исправлена (указанная Н.Гуриным) ошибка в обработке событий MouseWheel (прокрутка колесика мышки) в окнах мнемосхем. Ошибка была связана с неверныи расчетом координат, которая, вероятно, связана с переходом от MDI к SDI. Вроде бы теперь всё работает верно.
Исправлена ошибка в обработке событий Выход, т.е. закрытия главного окна и выхода из программы. Ошибка проявилась при наблюдении работы TrayIcon. При выборе команды Выход (закрытие окна) появляется модальный диалог подтверждения выхода. При этом была возможность повторно (рекурсивно) вызвать тот же диалог подтверждения выхода по команде из TrayIcon. Раньше такой ситуации не возникало, т.к. в области уведомлений не было меню с командой Выход. Хотя ситуация потенциально была возможной.
Проблема была в процедуре обработки FormCloseQuery, где запрашивалось разрешение закрыть программу. Теперь в этой процедуре рекурсия запрещена и повторный (рекурсивный) запрос подтверждения игнорируется. То есть всё должно работать корректно.
Сделаны более подробные сообщения в процессе загрузки и запуска
программы. Это управляется параметром
crwdaq.ini [System] VerboseLogon = 1.
Столкнувшись с проблемой рекурсии в обработчике
FormCloseQuery, решил (в качестве превентивной меры
безопасности) сделать защиту от рекурсии в таймерных процедурах.
Напоминаю, что у нас многие функции опроса реализованы в виде списка
процедур, вызываемых по таймеру. Внутри этих процедур (теоретически)
может возникать (косвенная) рекурсия - например, через вызов
Application.ProcessMessages. Чтобы избежать
потенциальных проблем рекурсивных вызовов, уровень рекурсии в функции
запуска таймерных процедур ограничивается уровнем
crwdaq.ini [System] MaxTimerRecursionLevel = 1.
Значение 1 означает, что разрешен только один уровень
вызова (первичный), а все рекурсивные вызовы отвергаются. Значение
0 отключает проверку уровня рекурсии.
Потенциально ограничение уровня рекурсии таймеров повышает отказоустойчивость программы. Это стоило сделать уже давно.
Была продолжена большая работа по привязке диалогов к окнам. Она сделана для окон CurveWindow, SurfWindow, TextEditor, а также (частично) для главного окна. Вроде бы так удобнее.
У нас давно и активно используется группа функций обработки слов (word): ExtractWord и другие. У этих функций есть ограничение - они не умеют работать с кавычками. А это иногда бывает нужно.
Теперь сделана группа функций для обработки фраз (phrase). Фразами считаются либо простые слова (без кавычек, не содержащие пробелов), либо закавыченные группы слов (в кавычках пробелы допускаются). Новая группа функций обработки фраз содержит, например, функции PhraseCount, ExtractPhrase, SkipPhrases, которые очень похожи на соответствующие функции обработки слов - WordCount, ExtractWord, SkipWords.
В настоящее время эта группа функций реализована в FreePascal. Вероятно, в будущем она будет добавлена в DaqPascal.
Серьезно доработан диалог для редактирования текста TextEditDialog. Это модальный диалог редактирования текста, который, например, вызывается при редактировании паспорта (комментария) к кривым и окнам.
Теперь в диалоге реализован полноценный Undo /
Redo. Доработан интерфейс. Модуль, в котором содержится
код TextEditDialog, исключен из списка черновиков,
помеченных флагом SKIP_DRAFT.
Веден параметр crwdaq.ini [System] TextEditDialog = 1 - режим редактирования для диалога. Если стоит 1, то в диалоге по умолчанию стоит режим ReadOnly, который снимается кнопкой с изображением амбарного замка.
В окнах кривых CurveWindow сделана привязка основных диалогов для настройки диапазона, параметров кривых и окон, а также редактирования паспорта кривой, к координатам окна. Это должно сделать работу с окнами удобнее - диалоги появляются над тем окном, которое редактируется, а не в центре экрана, как было раньше.
В функцию ParamStr добавлены параметры:
ParamStr('SessionNumber') // номер текущей сессии программы crwdaq, например 1
ParamStr('SessionNb') // номер текущей сессии программы crwdaq, например 1
ParamStr('SessionTitle') // заголовок текущей сессии программы crwdaq, например crwdaq#1/5123@crwbox
ParamStr('SessionName') // имя текущей сессии программы crwdaq, например crwdaq_1Эти параметры служат для облегчения идентификации сессий программы crwdaq. Вдобавок к этому есть переменные окружения.
Параметры сессий нужны для определения расположения рабочих каталагов (например, журнальных файлов), для поиска окон (имя окон формируется из идентификаторов сессий) и процессов. Такая информация бывает нужна для организации взаимодействия процессов в сложных программных комплексах.
В нескольких местах библиотеки StdLibrary обнаружены и устранены проблемы с кроссплатформенной совместимостью (где была привязка к Windows или Crw32).
В библиотеке _crw_meta.pas и зависящей от неё утилите textmetadata была найдена и исправлена серьезная ошибка. Ошибка состояла в том, что контрольная сумма защищаемого текста зависела от вида EOL, т.е. CRLF или LF. Из-за этого файл, защищенный под Unix, определялся как поврежденный под Windows и наоборот.
Сейчас текст принудительно приводится к виду CRLF перед подсчетом контрольных сумм, чтобы сохранить совместимость со старой версией textmetadata, которая работает в Crw32 под Windows. Поэтому контрольные суммы теперь считаются правильно.
После исправления утилиты были заново обработаны все файлы калибровок .cal в каталоге demo и resource, так как они были защищены ошибочной версией textmetadata.
Были сделаны, т.е. скопированы из Crw32 и адаптированы для crwdaq, служебные сценарии под Windows:
Действия при запуске/завершении новой версии пакета под Windows теперь практически такие же как в старой версии (как и должно быть).
Сделаны проправки в библиотеке StdLibrary, касающиеся PostMortalWill.
Параметр crwdaq.ini [DAQ.Devices.Default.PostMortalWill] задает сценарий обработки критического сбоя программ DaqPascal.
Теперь в этом сценарии можно использовать подстановки:
Работа PostMortalWill проверена под Unix и Windows. Всё работает.
Добавлен отладочный канал
_FormDefaultHandler. Это канал для
необработанных сообщений визуальных форм, которые
попадают в процедуру TMasterForm.DefaultHandler, где
перехватываются и (при необходимости) журналируются. Событий может быть
много, поэтому надо соблюдать осторожность при работы с этим каналом,
использовать фильтры для облегчения поиска нужных событий.
Канал введен для облегчения отладки окон.
Частично восстановлена и проверена работоспособность интерфейса баз данных DbApi (пока только в версии для Windows). По крайней мере, диалог DataBase Browser заработал (проверялся на SQLight). Это хороший знак, немного повозиться с сервером &FbdSrv - и восстановление DbApi будет полным. А потом и для Unix сделаем DbApi.
Переведена и проверена под Windows демо конфигурация demo_dbquery. Вроде бы под Windows всё работает. Под Unix пока не реализована библиотека DbApi, поэтому там это пока недоступно.
Переведен и адаптирован к новой версии пакета сервер &FdbSrv. Он
проверен под Windows на демо конфигурации
demo_dim_ping - вроде бы работает
успешно.
Таким образом, в новой версии пакета библиотека интерфейса к базам данных DbApi, диалог DataBase Browser и сервер &FdbSrv - работают под Windows в полном объеме. Реализация DbApi под Unix - планируется после выхода первого релиза. А пока двигаемся дальше.
Была продоложена работа по устранению разных мелких недочетов.
Доработаны и удалены несколько “черновых” фрагментов кода,
помеченных как SKIP_DRAFT. Еще пара файлов
“очистилась” от статуса “черновиков”.
Продолжена работа по замене строк ShortString на LongString. В будущем релизе должен остаться минимум коротких строк, код будет работать в основном с длинными строками.
В компиляторе DaqPascal поправлена функция
PidAffinity, которая была помечена как черновик
(SKIP_DRAFT).
В новой версии пакета crwdaq для интерфейса
пользователя используется универсальная кодировка UTF8.
Однако, поскольку Windows и старая версия
Crw32 (еще) работают, в файлах или потоках данных могут
присутствовать также строки в кодировке ANSI, обычно
CP1251. Поэтому есть потребность в механизме
автоматического преобразования строк так, чтобы читались корректно
строки как UTF8, так и CP1251.
Конкретно эта проблема возникла с чтением файлов формата
*.crw, созданными в старой версии
Crw32.
Следующие функции созданы для решения этой проблемы.
В модуле _crw_utf8.pas
добавленв глобальная переменная TheFavoriteAnsiCodePage
и функция
utf8_fix_cp(s:string; cp:integer):string.
Функция utf8_fix_cp(s,cp):string служит
для исправления (fix) кодировки (cp=CodePage), чтобы
получить UTF8 строку результата. Сначала функция
проверяет, является ли строка s корректной строкой
UTF8. Строки формата UTF8 возвращаются
без изменений. Если строка не является корректной строкой
UTF8, то делается попытка преобразовать её из кодировки
cp в UTF8.
Глобальная переменная TheFavoriteAnsiCodePage
содержит “любимую” (предпочитаемую) кодировку, используемую в функции
utf8_fix_cp для коррекции строк в
кодировке ANSI, т.е. отличной от UTF8.
Точнее, если в функцию utf8_fix_cp(s,cp)
передается cp=0, то вместо нуля берется
cp=TheFavoriteAnsiCodePage.
В Главной Консоли добавлены две функции для доступа к TheFavoriteAnsiCodePage:
SetFavoriteAnsiCP(1251) # задать предпочитаемую кодовую страницу TheFavoriteAnsiCodePage
GetFavoriteAnsiCP() # прочитать предпочитаемую кодовую страницу TheFavoriteAnsiCodePage
# Кодовые страницы:
# 866 Русский,DOS/OEM
# 1251 Русский,Windows
# 65001 Unicode,UTF8
# 0 Преобразование отключеноЗначение TheFavoriteAnsiCodePage в модуле задается
как 0 (преобразование отключено).
Однако в стартовом сценарии crwdaq.ini
[System.StartupScript] делается вызов
SetFavoriteAnsiCP(1251), который
устанавливает TheFavoriteAnsiCodePage = 1251.
Пакет Crw32 записывает файлы формата
*.crw со строками в кодировке
CP1251, которая используется в Windows
для русского языка. В новой версии пакета crwdaq
основной кодировкой является Unicode UTF8, поэтому
файлы формата *.crw читались в искаженном
виде (нечитабельные строки).
Теперь эта проблема исправлена.
Код чтения файлов формата *.crw изменен
с использованием функции
utf8_fix_cp.
Функция utf8_fix_cp используется для
коррекции при чтении строк в файлах формата
*.crw. Для преобразования строк
используеся TheFavoriteAnsiCodePage, которую можно
задавать вызовом функции SetFavoriteAnsiCP(…). По
умолчанию при старте пакета задается
SetFavoriteAnsiCP(1251), чтобы считывать файлы старой
версии без ошибок.
Таким образом, поддержка UTF8 для файлов формата
*.crwсущественно улучшена. Терерь корректно читаются*.crwфайлы как новой, так и старой версии пакета.
В компиляторе DaqPascal доработан вызов внешнего редактора - теперь ему передаются (кроме прочего) код ошибки и сообщение об ошибке от компилятора.
Доработана утилита daqpaseditor.sh для вызова
внешнего редактора. Теперь он сохраняет все нужные параметры в
промежуточный файл типа
$HOME/.local/share/daqgroup/daqpaseditor/crwdaq_1.ini,
затем вызывает внешний редактор, а также (при наличии ошибки) выводит
сообщение об ошибке во всплывающем окне.
Сделана утилита daqpascompile.sh для компиляции программ DaqPascal из внешнего редактора. Эта утилита берет данные из промежуточного файла, подготовленного вызовом daqpaseditor.sh и вызывает команду компиляции.
Для разработки программ DaqPascal в качестве основного внешнего редактора был выбран geany, а в качастве резервного (запасного) kate (на случай отсутсвия geany).
Были подготовлены и добавлены конфигурационные файлы для geany, которые при вызове редактора копируются в $HOME/.config/daqgroup/geany и служат для организации сессий geany, привязанных к сессиям crwdaq. В этих конфигурационных файлах есть код вызова компилятора DaqPascal, что позволяет “замкнуть” цикл редактирования/компиляции. Команда вызывается по кнопке Компиляция на панели инструментов geany.
В резервном редакторе kate “замыкание” цикла разработки пока не реализовано, но оно тоже возможно. Возможно, когда-нибудь вернемся к этому. А пока просто пользуемся geany.
Таким образом, тема внешнего редактора (пока) закрыта. Можно вести разработку как во внутреннем (простом) редакторе, так и в “продвинутом” редакторе geany с подсветкой синтаксиса и другими полезными “плюшками”.
При использовании внешнего редактора надо не забывать, что компилируется на самом деле не файл, а устройство, связанное с этим файлом. Связка файла с устройством устанавляивается в момент открытия внешнего редактора в пакете crwdaq, точнее при вызове команды daqpaseditor.sh, которая сохраняет всю нужную информацию в промежуточном ini файле. Напомним, что в ряде случаев (например, драйверов) может быть много устройств, имеющих один и тот же код. Компилироваться будет то устройство, для которого был открыт редактор. Другие устройства с тем же файлом кода программы будут работать с прежним кодом, пока не будут явно скомпилированы или перезагружены.
Примечание: всё сказанное про внешний редактор относится к Linux версии. Под Windows в качестве внешнего редактора используется Notepad++. В нём пока компиляция не реализована.
В добавление к параметру
[DAQ] OutFifoCleanDelay введен параметр
[DAQ] OutFifoCleanRunCount = 1e5. Этот
параметр применяется, чтобы производилась очистка буфера
Fifo консоли устройств DaqPascal, если
RunCount > OutFifoCleanRunCount.
Напомним, была обнаруженв проблема с потерей консольного вывода при
старте программ DaqPascal из-за того, что окно консоли
(еще) не открыто. Для устранения проблемы была введена задержка,
удерживающая консольный вывод в буфере в течение
OutFifoCleanDelay, чтобы дать окну время открыться.
Параметр OutFifoCleanRunCount фактически отключает
задержку после
RunCount > OutFifoCleanRunCount. Это
нужно для оптимизации работы консоли - после старта, когда прошло
достаточно много времени, задержка уже не нужна, т.к. консольное окно
уже открылось. Условие по RunCount позволяет отключить
ненужную задержку, которая может вызвать увеличение потребления памяти,
если идет интенсивный вывод в консоль.
Для унификации (одинаковости) поведения кнопки в Области Уведомлений под Linux и Windows было решено сделать так, чтобы по “клику” (щелчку левой кнопкой мыши) на кнопке показывалось всплывающее меню Popup, а не просто восстановление (активизация) окна программы. Такое поведение управляется параметром crwdaq.ini [System] TrayIconPopupOnClick = 1. Если поставить значение TrayIconPopupOnClick = 0, то по клику будет выполняться восстановление окна программы под Windows, а под Linux тоже появится меню (особенность реализации LCL).
Короче, сейчас по щелчку левой и правой кнопкой мышки будет вылезать меню в обоих системах (чтобы было одинаково).
Кажется, тема TrayIcon (пока) закончена. Двигаемся дальше.
Была исправлена обнаруженная А.Жируновым проблема с компилятором DaqPascal, которая заключалась в том, что иногда при ошибках компиляции выдавались неверные значения позиции ошибки (номера колонки). Эта проблема возникала при наличии символов Unicode - например, строк на кириллице. Связано это с тем, что в старой версии использовалась однобайтовая кодировка символов, где байтовая и символьная позиция совпадают. В новой версии, где используется кодировка UTF8 с переменным числом байтов на символ, номер колонки в символах не всегда совпадает с байтовой позицией, которая и выдавалась в сообщениях, т.к. компилятор работает именно с байтовой позицией символов. Теперь в нужных местах, где выдаются сообщения об ошибках компиляции, по известной байтовой позиции ошибки вычисляется её символьная позиция и выдается в качестве результата. Так что теперь сообщения об ошибках должны быть корректными.
Кроме того, было обнаружено, что в Windows версии из-за особенностей обработки EOL в случае файла в формате Windows с разделителями CRLF выдавался неверный номер строки - примерно вдвое больше реального. Это происходило потому, что строка с разделителем CRLF воспринималась как две строки (вторая строка пустая). На компиляцию это не влияло, но номер строки получался неверным. Теперь после символа CR ожидается символ LF и другой символ воспринимается как ошибка. То есть компилятор нормально “глотает” исходные файлы с разделителем LF или CRLF, но разделитель CR без LF или LFCR приведет к ошибке с сообщением о повреждении файла.
Исправлено также позиционирование курсора на месте ошибки - как во внутреннем, так и во внешнем редакторе. В редакторах при работе с текстами UTF8 позиция курсора обычно указывается в символах, а не в байтах. Поэтому при позиционировании курсора также используется вычисление символьной позиции по байтовой.
По результатам совещания было принято решение всё-таки задать
значение по умолчанию UsesSysTray = 1, то
есть показывать кнопку в Области Уведомлений при старте
программы, как в старой версии Crw32. Уже все привыкли.
Да будет так.
Было замечено, что если в .desktop ярлыках для
запуска сессий crwdaq стоит командная строка типа
Exec=/opt/crwdaq/crwdaq --session 2 %f (со
знаком подстановки %f на конце), то оконный менеджер
Fly при запуске ярлыка из меню Пуск
игнорирует аргументы и интепретирует его как запуск
Exec=/opt/crwdaq/crwdaq, т.е. как запуск
программы без аргументов. Интересно, что если убрать знак подстановки
%f, либо поставить вместо него конкретное имя файла, то
всё работает верно. Кроме того, при запуске ярлыка с знаком подстановки
%f из оболочки (например, из
DoubleCommander или Менеджера Файлов)
всё тоже работает верно. Видимо, это какой-то глюк реализации меню
Пуск в Fly. Потому что исходя из стандарта
всё должно было работать и со знаком подстановки
%f.
Проблема вылечилась, когда из ярлыка был убран знак подстановки %f. Теперь запуск сессий в меню Пуск работет верно.
Правда, теперь (если следовать стандарту) на ярлыки уже не получится “схватить и бростить” конфигурационный файл для запуска DAQ-системы, т.к. без подстановки %f будет просто запускаться программа без передачи ей имени файла. Но вроде мы этим и не пользуемся. Поэтому это выглядит приемлемой ценой.
В Главной Консоли добавлена команда
@TrayIcon:
@trayicon -visible 1 # показать кнопку в Области Уведомлений
@trayicon -visible 0 # удалить кнопку из Области Уведомлений
v=@trayicon -visible # прочитать статус кнопки в Области УведомленийКоманда @TrayIcon -visible 1 показывает
кнопку (иконку) в Области Уведомлений (System
Tray). Кроме того, эта команда убирает кнопку приложения из
Панели Задач. Это делается для того, чтобы не
дублировать кнопки - если кнопка есть в Области
Уведомлений, она уже не нужна на Панели
Задач.
Команда @TrayIcon -visible 0 убирает
кнопку (иконку) из Области Уведомлений, а также
возвращает кнопку приложения на Панели Задач.
Команда @TrayIcon -visible возвращает
статус (Visible) кнопки в Области
Уведомлений.
Кнопка в Области Уведомлений содержит меню (по правой кнопке мыши), позволяющее пользователю Свернуть или Восстановить приложение, а также Завершить его. Для сохранности команда завершения запрещена, если загружена DAQ-конфигурация.
К сожалению, кнопка в Области Уведомлений работает немного по-разному в Windows и Linux. В Windows по щелчку левой кнопки мыши происходит восстановление (активизация) приложения, а по правой кнопке - вызывается меню. В Linux по левой кнопке тоже происходит вызов меню. Видимо, это особенность реализации.
Кнопка в Области Уведомлений - удобный способ быстрого доступа к приложению, особенно когда много окон и мониторов или Рабочих Столов. Область Уведомлений находится в постоянном месте и не перегружена избыточным количеством кнопок (обычно), что ускоряет поиск приложения. Кроме того, кнопку в Области Уведомлений видно всегда, каким бы ни был активный Рабочий Стол.
Сеансы crwdaq отличаются по цвету картинки и легко различаются между собой. Поэтому нужный сеанс можно быстро найти в Области Уведомлений, даже если работает несколько сеансов crwdaq.
Параметр crwdaq.ini [System] UsesSysTray в старой версии Crw32 определял состояние кнопки в Области Уведомлений (0/1=прятать/показывать). Это состояние после старта пакета нельзя было изменить. Теперь, с появлением команды @TrayIcon, состояние кнопки в Области Уведомлений можно менять в процессе работы.
Было решено параметр UsesSysTray оставить в силе - теперь он вызывает при старте команду @TrayIcon, однако значение по умолчанию изменено на 0. То есть по умолчанию кнопка в Области Уведомлений не показывается, но её всегда можно включить. Решение об использовании кнопки в Области Уведомлений перекладывается на конкретное приложение. Предполагается, что где-то в секции [&CronSrv.StartupScript] будет помещаться вызов команды @TrayIcon, который приведет кнопку в нужное состояние.
Возможно, после накопления опыта работы с @TrayIcon, значение по умолчанию для параметра UsesSysTray будет снова изменено на 1. Потребность в этом изменении покажет опыт.
Проведена доработка функции ListBoxMenu, которая отображает диалог со списком. Этот диалог используется очень часто и весьма важен для работы программы. Проблема была в автоматической разметке - подгонка размера окна списка меню к тексту, который в списке отображается. Геометрия отображения списков немного отличается в разных системах (в том числе отличается от VCL), поэтому пришлось немного повозиться, чтобы настраивать её для LCL под gtk2 и win32.
Аналогично сделана доработка функции CheckListBoxMenu, которая отображает диалог со списком и “чекбоксами”, где можно ставить “галочки”. Этот диалог используется гораздо реже (в основном когда надо указывать битовые маски), и работает аналогично.
В результате вроде бы удалось добиться приемлемого качества автоматической разметки, при которой размер окна со списком подгоняется так, чтобы список был виден (по возможности) весь, но пустые поля не были бы чрезмерно большими.
Код был проверен под Unix и Windows.
Небольшие внутренние изменения в коде реализации окон. Некоторые повторяющиеся фрагменты кода оформлены в виде функций. Это улучшит модульность кода, а потому и его управляемость.
Работа над оконной системой продолжается.
К вчерашней теме (о печати).
Печать текстовых окон сделана по аналогии с другими окнами, т.е. печатается изображение окна редактора, а не текст. Это немного не то, что можно ожидать от печати в редакторе, но пока этого достаточно. Для печати текста можно скопировать текст в другой (внешний) редактор и распечатать текст из него. Возможно, печать текста будет сделана, но позже. А пока будем решать более насущные проблемы.
Доработаны под Unix функции, связанные с шрифтами - список шрифтов, поиск шрифтов по заданным характеристикам и т.д.
Это позволило поправить команду @fonts,
которая была (частично) закомметирована с пометкой
SKIP_DRAFT (черновик). Теперь команда
работает (в первом приближении) корректно под Unix и
Windows. Некоторы подфункции (типа @fonts add) под
Unix (пока) не реализованы, т.к. пока не видно в этом
необходимости. Они выдают соответсвующее сообщение.
В результате еще один модуль (из примерно 15 оставшихся) освободился
от статуса “черновик”. Такой статус имеют модули, имеющие фрагменты
кода, закомментированные с пометкой
SKIP_DRAFT. По мере приближения к релизу
такие модули будут вычищаться.
Поскольку функции работы с шрифтами под Linux
реализованы через команду fc-list из пакета
fontconfig (он есть в репозитории), то обновлена
утилита unix crwdep, которая проверяет
зависимости пакета. В неё добавлены пакеты fontconfig,
daqgroup-dunst и другие, нужные для (комфортной) работы
crwdaq.
Исправлены проблемы печати для всех основных типов окон (консоли, таблицы, мнемосхемы, окна с кривыми, окна с поверхностями).
Реализованы функции Файл/Печать:
Все функции проверены и работают под Linux/Windows.
Теперь точно можно сказать, что вопросы печати (пока) закрыты.
Еще не реализована печать текстовых окон (на принтере), но есть вопрос - а надо ли её делать. Вполне достаточно копирования/вставки и печати во внешнем редакторе. Поэтому пока этот вопрос отложен.
При тестировании были обнаружены некоторые проблемы с работой меню Файл/Печать. Точнее, были найдены проблемы с выполненим пункта “Скопировать изображение в Буфер Обмена”. Изображение вроде бы копировалось, но многие графические редакторы под Linux это изображение не видели, как будто буфер обмена оставался пустым. Как выяснилось, проблема заключалась в том, что по умолчанию изображение создавалось в формате image/bmp, а это не “родной” для Linux формат, используемый в основном под Windows. То есть изображение в буфере было (и виртуалки под Windows его видели), но графические программы его не обнаруживали, потому что такой формат ими не поддерживается.
Для решения проблемы изображение теперь копируется в формат image/png, который является “родным” для Linux. При этом большинство графических редакторов Linux такое изображение без проблем распознают. Проблема с Буфером Обмена для изображений была (в первом приближении) решена.
Была исправлена работа меню Файл/Уставки Принтера:
Предполагается, что в дальнейшей работе используются выбранные параметры печати.
Для сведения. В репозиторий Linux входит полезный PDF принтер cups-pdf, позволяющий делать печать в PDF файлы. Инсталляция:
sudo apt install cups-pdfПапка назначения для печати задается в параметре Out
файла /etc/cups/cups-pdf.conf. По
умолчанию это папка $HOME/PDF. Именно туда
будут помещаться напечатанные .pdf файлы.
Полезность PDF принтера в том, что он позволяет печатать документы, даже если нет физического принтера. Распечатать полученные файлы можно позже из файлов на другом компьютере. Кроме того, печать в PDF полезна для создания документации.
Были сделаны исправления для корректной печати изображений окон.
Проблемы с печатью были связаны с масштабированием малых и обрезанием больших изображений, а также с отступами при печати. Пришлось немного повозиться, чтобы реализовать заданные в диалоге настройки печати отступы, масштабировать изображение с учетом заданного размерного фактора и обрезания. Для устраниения обрезания больших изображений фактор масштаба выбирается так, чтобы изображение поместилось в поле печати (это делается если указан параметр “Подгонка размера”).
Таким образом, в первом приближении функции печати готовы к работе. Пока функции печати поправлены для консольных окон, остальные типы окон будут сделаны вскоре.
В пакет crwkit добавлена утилита colorcode, которая печатает RGB код цвета по его имени в различных форматах. Формат указывается в опциях, имена цветов - в списке параметров. Можно задать список цветов - и для каждого цвета будет выведен его код в отдельной строке. Это сделано для сокращения накладных расходов - одним вызовом можно получить коды сразу нескольких цветов, причем почти за такое же время, как для одного цвета.
Утилита colorcode использует такую же таблицу имен цветов, как пакет crwdaq. Если имя цвета не находится в таблице, печатается это имя (без изменений), а также возвращается код ошибки.
Примеры:
# Вывести коды цветов в десятичном формате
$ unix colorcode red lime blue
| 255
| 65280
| 16711680
# Вывести коды цветов в WEB формате #rrggbb
$ unix colorcode -web red lime blue
| #ff0000
| #00ff00
| #0000ff
# Вывести коды цветов в HEX формате 0xbbggrr
$ unix colorcode -hex red lime blue
| 0x0000ff
| 0x00ff00
| 0xff0000
# Вывести коды цветов в формате Pascal $bbggrr
$ unix colorcode -pas red lime blue
| $0000ff
| $00ff00
| $ff0000
# Напечатать справку
$ unix colorcode --help
| colorcode.sh version 1.0
| Copyright (c) 2024 Alexey Kuryakin daqgroup@mail.ru
| Print color code(s) by given color name(s).
|
| Syntax: colorcode.sh [options] [arguments]
|
| Options: -- => end options
| --version => show version
| -h,--help => show help screen
| -d,--dec => print color as decimal (default)
| -w,--web => print color in WEB format #rrggbb
| -x,--hex => print color in HEX format 0xbbggrr
| -p,--pas => print color in HEX format $bbggrr
| -l,--list => print list of colors as 'name ggbbrr'
|
| Arguments: list of color names to convert
|
| Notes:
| 1) If color name not found, print color name and return error code
| 2) The (rr,gg,bb) are (red,green,blue) codes in HEX (%2.2x) format
| 3) Options (-opt,--opt) are both valid, so (-dec,--dec) are equals
|
| Examples: colorcode.sh --help
| colorcode.sh --version
| colorcode.sh --list
| colorcode.sh black white
| colorcode.sh -x maroon lime navy
| colorcode.sh -web red green blueУтилита colorcode будет полезна для сценариев bash, работающих с именованными цветами. Например, многие программы требуют указания цветов в числовом виде или в виде WEB кода. Утилита colorcode поможет транслировать имена цветов в необходимые этим программам цветовые коды. Собственно, утилита первоначально сделана для подготовки цветов в утилите tooltip-notifier, но будет полезна и для других приложений.
Произведена доработка кода утилиты
unix tooltip-notifier с учетом появления
dunst и утилиты colorcode. Добавлена
поддержка звуков. Добавленв поддержка цветов, которые теперь приведены в
соответствие с настройками preset. Другими словами,
теперь tooltip-notifier под Unix
работает почти так же (с той же расцветкой и звуками), как
FPQUI под Windows. Правда, было решено
уменьшить размер шрифта, чтобы сообщения не сильно загромождали экран.
Но в целом рскраска и поведение tooltip-notifier
максимально приближено к FPQUI, насколько это было
возможно и целесообразно.
В утилите tooltip-notifier также была добавлена
опция --ini:
unix tooltip-notifier --ini "sound-on 1" # включить звуки
unix tooltip-notifier --ini "sound-on 0" # отключить звукиС помощью опции --ini можно
включить/отключить поддержку звуков. Состояние звука сохраняется в файле
$HOME/.config/daqgroup/tooltip-notifier/tooltip-notifier.ini,
в секции [tooltip-notifier], в параметре
sound-on в виде числового значения
0/1. Это позволяет отключить звуки всплывающих
уведомлений, если они мешают.
На этом тема всплывающих уведомлений (пока) закрыта.
Базовый функционал tooltip-notifier теперь обеспечен.
Доработки, если они будут нужны, будут делаться в рабочем порядке.
Для чтения/записи параметров программ часто используются INI файлы. Программа git config (которая обычно установлена) позволяет довольно легко это организовать в сценариях bash:
# Прочитать ключ key из секции [section] INI файла
git config -f $HOME/.config/vendor/program/config.ini section key
# Записать value в параметр [section] key INI файла
git config -f $HOME/.config/vendor/program/config.ini section key valueЭтот способ чтения/записи INI в файлы успешно
использован в tooltip-notifier. Так что вариант вполне
рабочий, хотя и имеет свои ограничения. Например, имена ключей и секций
могут включать символы [a-z0-9-], но не
должны сдержать в имени точку (.) и подчеркивание (_).
Для работы с INI файлами была написана такая функция:
#######################################################################################################
# get/set INI file parameter:
# git_ini -get inifile section key
# git_ini -set inifile section key value
# git_ini -get $HOME/.config/daqgroup/tooltip-notifier/tooltip-notifier.ini tooltip-notifier sound-on
# git_ini -set $HOME/.config/daqgroup/tooltip-notifier/tooltip-notifier.ini tooltip-notifier sound-on 1
#######################################################################################################
function git_ini(){
local op="$1"; local ini="$2"; local sec="$3"; local key="$4"; local val="$5";
case $op in
-get|--get) if [ $# -eq 4 ] && [ -e "$ini" ]; then git config -f $ini $sec.$key; else return 1; fi; ;;
-set|--set) if [ $# -eq 5 ] && mkdir -p "$(dirname "$ini")"; then git config -f $ini $sec.$key "$val"; else return 1; fi; ;;
*) return 1; ;;
esac;
};Эту функцию можно использовать и для других сценариев bash, где требуется чтение/запись в INI файлы.
В сборку добавлен пакет daqgroup-dunst,
который устанавливается install-daqgroup-dunst.deb.
В дальнейшем мы будем называть его просто
dunst, т.к. это его оригинальное имя,
которое пришлось (вынужденно) немного модифицировать. Также добавлена
утилита dunstcfg для облегчения настройки
dunst после установки.
Пакет daqgroup-dunst - это новая (для нас) система
уведомлений, похожая (при должной настройке) на пакет
FPQUI, который используется в Crw32
под Windows. За основу daqgroup-dunst
был взят пакет dunst версии 1.5.0 из
Debian. Этот пакет был переименован в
daqgroup-dunst и модифицирован, т.к. не проходил по
зависимостям - конфликтовал с fly-fm. Пришлось его
немного “подкрутить”. Также были изменены настройки, находящиеся в
/etc/xdg/dunst/dunstrc,
которые наиболее подходят для наших задач. Этот файл настроек по
умолчанию надо скопировать в текущий файл настроек
$HOME/.config/dunst/dunstrc. Также, после
установки пакета daqgroup-dunst, надо деактивировать
или деинсталлировать другие серверы уведомлений - например,
qtnotifydaemon или
notification-daemon.
Новая система уведомлений daqgroup-dunst (или просто dunst) имеет много достоинств - малый размер, скромное потребление ресурсов, историю уведомлений, поддержку картинок, цветов и шрифтов, и много других. Из всех протестированных систем она в наибольшей степени похожа на FPQUI, которая работает под Windows и является (для нас) эталонной системой уведомлений. Теперь почти все возможности FPQUI будут доступны под AstraLinux.
Пакет daqgroup-dunst устанавливает следующие программы:
dunst # сервер всплывающих уведомлений
dunstctl # управляющая программа для сервета dunst
dunstify # клиентская программа для сервета dunst
man dunst # справка по dunst
man dunstctl # справка по dunstctlСервер уведомлений dunst обычно НЕ вызывается напрямую. Он вызывается автоматически (системой DBUS), когда клиентские программы, например, notify-send, запрашивают всплывающее уведомление. Это работает так: клиентская программа notify-send формирует сообщение для сервиса org.freedesktop.Notifications и посылает его по протоколу DBUS серверу сообщений DBUS, который находит сервер, обслуживающий этот сервис. Список серверов, обслуживающих сервисы DBUS, хранится в *.service файлах в папке /usr/share/dbus-1/services. Всё это сервер сообщений DBUS делает прозрачно для клиентов, детали не должны их волновать. Важно лишь, что нужный сервер находится и выполняет обработку сообщений - в данном случае это вывод всплывающих уведомлений.
Хотя в пакете dunst есть свой клиент
dunstify для вызова сообщений, сервер
dunst прекрасно работает через общий интерфейс
notify-send. Он также работает с утилитой
unix tooltip-notifier, которая
интегрирована в пакет crwkit и является основным
методом уведомлений в пакете crwdaq.
Утилита unix tooltip-notifier слегка
поправлена для совместимости с dunst.
Соответственно сделанным изменениям обновлен пакет
install-daqgroup-all.run.
Для облегчения настройки dunst в пакет crwkit добавлена утилита dunstcfg.
# Получить список работающих процессов dunst
$ unix dunstcfg -list
26126 /usr/bin/dunst
# Убить работающие процессы dunst
$ unix dunstcfg -kill
dunst killed (pid 26126)
# Обновить или создать локальную конфигурацию dunst
# Копирует конфигурацию из шаблона в папку пользователя
$ unix dunstcfg --update
'/etc/xdg/dunst/dunstrc' -> '/home/alex/.config/dunst/dunstrc'
# Сделать dunst единственным сервером уведомлений
# Завершает/отключает другие серверы уведомлений, если они были
$ unix dunstcfg --single
qtnotifydaemon killed (pid 27806)
'/usr/share/dbus-1/services/org.freedesktop.Notifications.service' -> '/usr/share/dbus-1/services/org.freedesktop.Notifications.service.off'
# Вызвать справку
$ unix dunstcfg --help
dunstcfg version 1.0
The dunst configuration tool by DaqGroup.
Copyright (c) 2024 Alexey Kuryakin daqgroup@mail.ru
Help on dunstcfg:
====================> Syntax:
dunstcfg [Options] Arguments
====================> Options:
-- => options ending, next is params
--version => print program version and exit
-h,--help => print this help screen and exit
-u,--update => update local user configuration (dunstrc):
copy /etc/xdg/dunst/dunstrc to ~/.config/dunst/
-l,--list => list running dunst pid(s)
-k,--kill => kill running dunst pid(s)
-s,--single => make dunst a single notifier: unregister all other notifiers,
rename /usr/share/dbus-1/services/ *.service to *.service.off
for each service Name=org.freedesktop.Notifications
Notes:
1) Option -opt equivalent to --opt, so -kill is the same as --kill
1) Option executed in same order as it written, from left to right
====================> Arguments:
None => must be empty
====================> Exit Code:
Return 0 on success, otherwise return error code
====================> Examples:
dunstcfg --version
dunstcfg --help
dunstcfg --list
dunstcfg -u -s
dunstcfg -killУтилита была сделана потому, что в системе обычно уже установлен (один или более) сервер уведомлений, например, qtnotifydaemon. После установки dunst неизвестно какой из серверов уведомлений будет вызывается, так как сервер сообщений DBUS ищет серверы (по имени сервиса) в произвольном порядке. Поэтому хорошо бы отключить другие серверы уведомлений, кроме dunst. Кроме того, настройка параметров dunst для пользователя не делается автоматически. Автоматически (при инсталляции пакета) в папку /etc/xdg/dunst помещается шаблон dunstrc, который после инсталляции надо скопировать в папку $HOME/.config/dunst/ и (возможно) отредактировать.
Следующий вызов решает обе задачи:
unix dunstcfg -u -s # --update --single - обновить и сделать единственнымЭтот вызов вставлен в инсталлятор пакета crwdaq.
Небольшое примечание. Для отключения других серверов уведомлений утилита dunstcfg может переименовать в папке /usr/share/dbus-1/services некоторые *.service файлы в *.serice.off файлы (т.е. добавляет .off). Для возврата отключенных сервисов их надо переименовать обратно.
Поправлена команда
@Polling PriorityClass prio period,
которая устанавливает класс приоритета процесса
prio=(Idle,Lower,Normal,Higher,High,RealTime), а также
период проверки приоритета period в
миллисекундах.
Например:
@Polling PriorityClass High 1000 # Установить приоритет High и проверять каждую секундуВ старой версии пакета (Crw32 под Windows) в качестве приоритета процесса можно было указывать числовое значение уровня приоритета:
После перевода пакета под FreePascal эти (числовые) константы не работали из-за разницы в реализации. Теперь работают (для совместимости), т.к. они прописаны в большом числе DAQ-конфигураций.
Также поправлены Консольные Утилиты/CRW/Приоритет Процесса - crwdaq.utils.lm9. Чтение/запись приоритета не работали под Linux из-за разницы в системе приоритетов.
Подробнее о приоритетах процессов и потоков читайте тут.
Обновлены все install-*.run
инсталляторы, создаваемые утилитой makeself.
Суть изменений состоит в том, что теперь в каталоге
$HOME/.local/share/makeself сохраняются не
только файлы release-*.txt с меткой
времени, которые используются для контроля версий, но и журнальные файлы
install-*.log с протоколами
инсталляции.
Журнальные файлы могут помочь понять, что пошло не так, если при инсталляции возникли ошибки.
Создан сценарий check-daqgroup-all.sh, который проверяет целостность файлов пакетов crwdaq, crwlib, crwkit.
Этот сценарий полезен при сборке пакетов, а также после инсталляции для проверки целостности файлов после инсталляции и последующей эксплуатации.
В первом приближении решен вопрос (неверной) прорисовки окон после старта DAQ-системы. Этот эффект наблюдался только в Gtk2 - видимо, какая-то ошибка реализации библиотек визуальных элементов LCL WidgetSet. Он проявляется в том, что после старта DAQ-системы некоторые окна не обновляются или рисуются как-то неправильно (с обрезанием по некоторому прямоугольнику). Эффект исчезает, если немного “пошевелить” окно (изменить размеры окна). При дальнейшей работе эффект более не наблюдается, только при старте DAQ-системы. Предположительно, эффект возникает из-за наложения асихронных операций рисования при большом числе операций рисования окон после старта DAQ-системы.
Проблема вроде бы решена, хотя метод решения явно небезупречен. Он заключается в том, что программный код сам “шевелит” окно (меняет размер туда-обратно) после определенных событий (активизация, изменение состояния окна). Этот механизм назван CodePills (дословно - таблетки для кода). Это в общем работает, но достигается ценой избыточного числа операций прорисовки окон. Визуально это проявляется в “мигании” окна, когда оно получает фокус (становится активным). Это ничему не мешает, хотя немного раздражает.
Для разрешения CodePills введен флаг crwdaq.ini [System] EnableSdiFormCodePills = 1. Флаг позволяет отключить “таблетки для кода”, есди они не нужны. Возможно, в будущем ошибка в реализации LCL/Gtk2 будет исправлена или будет найден другой, более красивый способ решения проблемы прорисовки. А пока будем работать так.
Добавлен отладочный канал _DrawView. В
нем журналируются события (полной) прорисовки окна -
DrawView. Окна не всегда прорисовываются полностью -
например, может рисоваться отдельный сенсор или кусок кривой (обычно это
делается в цикле опроса). Канал _DrawView
фиксирует только запросы на полную прорисовку окна.
Такие операции рисования наиболее ресурсоемки и поэтому бывает полезно
их отслеживать.
Для управления отладочным выводом введены фильтры -
список шаблонов фильтрации. Они допускают или запрещают отладочный
вывод, если строка вывода удовлетворяет критериям фильтрации. Включающий
фильтр Include допускает отладочный вывод, если хотя бы
один фильтр верен. Исключающий фильтр Exclude запрещает
отладочный вывод, если хотя бы один фильтр верен. Отладочное собщение
печатается, если фильтры допускают и не запрещают вывод. Если фильтры не
заданы, вывод автоматически допускается. Фильтры можно добавлять в любом
количестве (хранится список фильтров). Если фильтр имеет формат
/RegExp/opt, то он рассматривается как
регулярное выражение RegExp с опциями
opt, иначе как простая строка. В случае простой строки
регистр не учитывается, а в случае регулярного выражения регистр играет
роль. Учет регистра можно отключить опцией /…/i, но
только для латинских символов.
Для управления отладочным выводом в Главной Консоли
сделана команда @DebugLogCtrl:
@DebugLogCtrl # справка
@DebugLogCtrl -l # вывод списка каналов отладки и фильтров
@DebugLogCtrl -r Test # регистрация нового канала отладки с именем Test
@DebugLogCtrl -i Консоль # включающий фильтр, допускает строки, содержащие "Консоль"
@DebugLogCtrl -e Главная Консоль # исключающий фильтр, запрещает строки, содержащие "Главная Консоль"
@DebugLogCtrl -i /_DrawView.*КОНСОЛЬ/i # включающий фильтр, допускает строки по шаблону регулярного выражения
@DebugLogCtrl -e /_DrawView.*ГЛАВНАЯ/i # исключающий фильтр, запрещает строки по шаблону регулярного выражения
@DebugLogCtrl -c 1 # очистка (запрещение) всех каналов отладки
@DebugLogCtrl -c 2 # очистка всех фильтров для каналов отладкиКаналы отладки с фильтрами позволяют очень гибко управлять отладочным выводом, что может сильно облегчить отладку как самого пакета, так и прикладных программ DaqPascal.
Устранена проблема с начальной (при старте DAQ-системы) прорисовкой окон под GTK2, которая делается через функции или сообщения @WinDraw, @WinShow и т.д. Эти функции используют отложенный вызов процедур - DPC (deferred procedure call), поскольку они вызываются из прикладных потоков DaqPascal, но выполняются в основном (графическом) потоке. Отложенный вызов процедур - это фактически очередь событий вызова указанных функций в цикле обработки событий. Механизм DPC нужен для потокобезопасного вызова функций рисования окон и других операций, выполняемых в основном потоке программы.
Как выяснилось в ходе исследований, при большом числе событий прорисовки окон в GTK2 возникают проблемы, связанные с нарушением последовательности операций с окнами. Вероятно, это связано с асинхронным характером X Windows (взаимодействием клиент-сервер), из-за чего графические операции не всегда работают так, как ожидалось. Происходит как бы “наложение” событий - следующее событие начинает обработку, пока предыдущее еще ожидает результата. Этого эффекта нет под Windows, где вызовы графических функций зачастую синхронны (не связаны с ожиданием), а также не наблюдаются при относительно малом числе операций, когда графические события поступают сравнительно редко и успевают обрабатываться в цикле обработки событий до поступления следующих событий.
Для устранения проблемы возникла идея использовать обработчик событий Application.OnIdle, который вызывается в цикле обработки основного графического потока после обработки всех событий в очереди. При этом выполнение команд из оччереди DPC производится по одной за раз, чтобы дать предыдущей команде DPC обработать вторичные (порожденные ею) графические события в очереди событий. Таким образом, команды, перенесенные из цикла событий в обработчик OnIdle, задерживаются до тех пор, пока не будут обработаны все предыдущие события в очереди. Возникает как бы двойная задержка - например, команда @WinDraw инициирует (вторичные) операции рисования, а затем следующая команда ждет, пока эти вторичные события не будут обработаны.
Тестирование показало, что введенный алгоритм обработки на основе OnIdle работает корректно и устраняет проблему начальной прорисовки окон. Пока не ясно до конца, не возникнет ли “побочных эффектов”, связанных с изменением очередности исполнения команд. Будем наблюдать и надеяться, что теперь всё будет работать верно.
Также введен параметр crwdaq.ini [System] SoftDev.HandleDpcOnIdle, который разрешает обработку DPC сообщений через цикл OnIdle. Если его отключить (занулить), всё будет работать по старому алгоритму. Это дает возможность быстрого “отката” к прежнему алгоритму обработки.
Добавлен счетчик SoftDev.DPC.Balance - баланс посылок/вызовов отложенных процедур (deferred procedure call), регистрируемый в файле утечек leakage.log.
Доработаны сценарии сборки пакета - теперь strip делается только при необходимости, то есть неизмененные бинарные файлы сохраняют дату, что облегчает контроль версий.
В библиотеку crwlib добавлен список процедур OnIdleActions, которые должны вызываться в Application.OnIdle, т.е. в цикле опроса после обработки всех событий из очереди событий. Служит для выполнения различных фоновых действий.
Также в окне Консоль Монитора Ресурсов добавлен счетчик App.OnIdle, измеряющий частоту событий Application.OnIdle.
В секцию [DAQ] добавлен параметр
OutFifoCleanDelay = 10000. Этот параметр
служит для устранения следующей проблемы.
Было обнаружено, что в консольных окнах DaqPascal происходила потеря консольных сообщений, которые посылаются при старте и инициализации программ. Как выяснилось, это происходило потому, что эти сообщения посылаются ДО открытия консольного окна. А если консольное окно (еще) не открыто, то поступающие сообщения удаляются (игнорируются). В старой версии пакета всё работало в силу деталей реализации - в секции [StartupScript] обычно стоит вызов @WinShow, который открывает консоль, и он успевал сработать до того, как проверялась консоль и очищался буфер. В новой версии это не срабатывает (выполнение [StartupScript] происходит позже) и происходит потеря сообщений.
Для устранения проблемы очистка буфера TProgramDevice.OutFifo теперь делается с задержкой в OutFifoCleanDelay миллисекунд, то есть в течение этого времени буфер не очищается. Если в течение этого времени открывается консоль, все сообщения сохранятся.
Поправка устраняет проблему потери начальных сообщений, однако возможен побочный эффект. При очень большом трафике буфер TProgramDevice.OutFifo может увеличиваться в размере и занимать больше памяти, т.к. очистка буфера теперь происходит гораздо реже. В буфере будет накапливаться объем сообщений, поступивших за время задержки, т.е. последних OutFifoCleanDelay миллисекунд. Если это будет создавать проблему, время задержки очистки можно уменьшить. По умолчанию время задержки равно 10000 - т.е. 10 секунд. При обычном (умеренном) трафике такая задержка не создает проблем, т.к. за это время не успевает накопиться существенный объем сообщений.
Создан отладочный канал _SdiForm для
сообщений, связанных с SDI окнами. В нем записываются
события изменения состояния SDI окон.
Канал сделан для отладки оконной системы.
Предприняты меры улучшения поддержки UTF8. Функция
IsSameText
теперь должна корректно работать с строками UTF8. Кроме
того, код функций группы winshow модифицирован так,
что должен верно работать со строками UTF8. Раньше
правильно работали только строки ASCII, а строки
Unicode сравнивались побайтно, т.е. регистрозависимо.
Это могло приводить к неверному результату сравнения строк на русском
языке (они всегда сравнивались с учетом регистра, хотя должны без учета
регистра). Функция IsSameText предполагает сравнение
без учета регистра, что могло приводить к проблемам, если строка (на
русском) задана в неверном регистре. Таким образом, теперь обе команды
@winshow КОНСОЛЬ &CronSrv и
@winshow консоль &CronSrv сработают
верно, в то время как раньше вторая из них не сработала бы из-за
неверного регистра строки.
В меню Пуск/Научные добавлены пункты меню:
- Менеджер
Сессий CRW-DAQ
- CRW-DAQ
Сессия 1
- CRW-DAQ
Сессия 2
- CRW-DAQ
Сессия 3
- CRW-DAQ
Сессия 4
- CRW-DAQ
Сессия 5
- CRW-DAQ
Сессия 6
Пункты меню соответствуют ярлыкам - т.е. .desktop файлам, отвечающим за запуск программ, см. спецификации freedesktop.org.
Ярлык CRW-DAQ Сессия n служат для вызова (пронумерованных) сессий crwdaq с номером n. При вызове возможно задание аргумента - загружаемого .cfg файла конфигурации DAQ-системы. По умолчанию в ярлыке используется аргумент %f, что означает “подставить аргумент вызова”. Например, если схватить мышкой файл и бросить его на ярлык, то ярлык запустится с этим файлом. Однако можно вместо %f задать (полное) имя конфигурационного .cfg файла, и тогда сеанс будет автоматически загружать эту конфигурацию при старте.
Ярлык Менеджер Сессий CRW-DAQ служит для вызова
диалога настройки ярлыков запуск сессий CRW-DAQ. Диалог
позволяет задавать каждой сессии свой .cfg файл
конфигурации, либо задать предопределенные аргументы
(%f - передать имя файла, %F -
передать список файлов, %u - передать один
URL, %U - передать список
URL). Также можно выполнить Сброс
(вернуть все ярлыки в начальное состояние), вызвать диалог
Настройка Автозапуска, вызвать диалог Настройка
Входа в Систему. Совместно эти функции позволяют гибко
управлять сессиями crwdaq и организовывать, например,
автоматическую загрузку сеанса данного пользователя, затем
автоматическую загрузку данной сессии crwdaq с
загрузкой данного .cfg файла конфигурации.
Таким образом организуется автозагрузка и автозапуск
DAQ-систем.
Исходные ярлыки (.desktop файлы) и сценарии (.sh, lm9) лежат в каталоге resource/launch, исходные картинки в resource/icon. Картинки копируются в /usr/share/pixmaps, .desktop файлы копируются в /usr/share/applications.
Имеется справка.
Также в Консольные Утилиты добавлена кнопка вызова Менеджера Сессий CRW-DAQ, чтобы он всегда был под рукой.
В нескольких модулях crwlib и crwdaq удалены проблемные
(отладочные) фрагменты с ключевым словом SKIP_DRAFT.
Это фрагменты кода, рассмотрение которых было отложено
в процессе перевода на FreePascal в расчете на вторую
итерацию редактирования, когда эти фрагменты будут проверены/исправлены.
Такие фрагменты помечались или исключались с помощью директив условной
компиляции
{$IFDEF SKIP_DRAFT}…{$ENDIF ~SKIP_DRAFT}.
Необходимость фрагментов SKIP_DRAFT была связана с
трудностями перевода кода - не все вопросы реализации были вполне ясны.
Исключение проблемных мест позволило ускорить процесс перевода и
получить почти рабочую версию пакета. Теперь настало время постепенно
разбираться с этими проблемными фрагментами и исправлять их. Осталось
порядка 15 модулей, где есть фрагменты
SKIP_DRAFT. Предполагается, что к моменту выхода
первого релиза все (или большинство) этих фрагментов будут
проверены/исправлены, а метки SKIP_DRAFT удалены.
Также проверенв обработка событий MouseWheel (прокрутка колесика мышки) в окнах мнемосхем. Вроде бы всё работает.
Сделан сценарий crwdaq.setsysmenu.sh для автоматического создания под Linux пунктов системного меню “Пуск/Научные/CRW-DAQ сессия 1…6”. Сценарий вызывается в процессе инсталляции пакета и создает все необходимые пункты Меню Пуск. Это будет “штатный” способ запуска сессий (экземпляров) пакета crwdaq из графической оболочки.
Дополнена программа unix crwdep, т.е. список зависимостей пакета crwdaq. В список добавлены samba и другие часто используемые сетевые протоколы и утилиты, которых (по недосмотру) не было в списке.
В библиотеки DieselPascal/External добавлены функции:
ExtractNameValuePair - выделение имени и значения из выражений “Name = Value”.
DaqConfig.ReadIniStr - чтение строки (параметра) из INI файла.
Эти функции нужны для чтения параметров из текстов или из файлов конфигураций в программах DieselPascal.
Исправлены утилиты demoping.lm9, testping.lm9 - две версии вызова ping.
Продолжена доработка Консольных Утилит.
По результату - Консольные Утилиты практически
готовы к (пробной) эксплуатации.
Большая часть (процентов 90) утилит сделана кроссплатформенной и
проверена.
Мелкие доработки утилит будут производиться в рабочем порядке.
Также обновлена сборка DIM - пакет daqgroup-dim.deb. Это связано с тем, что для обеспечения совместимости с crwdaq редактировались утилиты DimMonitor.lm9 и SmiGenGui.lm9, которые входят в сборку.
Консольные Утилиты переведены более чем наполовину (процентов на 80). То есть более половины функций работает в кроссплатформенном режиме Unix/Windows. Для облегчения перехода с Windows все кнопки сохранены, только делается вызов аналогичных функций в каждой системе. Некоторые кнопки под Unix запрещены, т.к. для них (пока) не нашлось аналога. Действия по кнопкам, вероятно, будут еще (не раз) редактироваться, но для начала - можно работать и так.
В меню Файл/Открыть (File/Open)
сделана обработка файлов DieselPascal с расширением
*.lm9. После задания типа файла
(Исполняемый) и выбора имени файла предлагается также
выбор способа обработки - Редактировать в Дизайнере или
Запустить как Программу. Новая функция полезна потому,
что часто требуется редактировать и/или запускать программы
DieselPascal в окружении пакета, т.е. в дочернем
процессе, когда наследуются переменные окружения пакета
crwdaq. При запуске/редактировании программы
DieselPascal извне (не из среды пакета) переменные
окружения пакета не наследуются и программы
DieselPascal могут работать неверно или не работать
совсем. Новая возможность представляет интерес (в основном) для
разработчиков программ DieselPascal.
Также продолжены работы по переводу команд Инструменты\Консольные Утилиты.
Сделан (начальный) перевод команды Инструменты\Консольные Утилиты.
Исправлен (сделан кроссплатформенным) вызов crwdaq.utils.lm9.
Исправлен (частично) файл настроек утилит crwdaq.utils.ini.
Консольные утилиты - очень большая тема, которую сложно сделать за
один раз.
На данный момент добился корректного вызова и частичной работы наиболее
часто используемых утилит.
Другая часть утилит еще не работает. Будем исправлять в ближайшее
время.
Также обновлены библиотеки DieselPascal (инсталлятор install-daqgroup-diesel-ext.run).
Проведена доработка демо конфигурации demo_dim_ping. В ней добавлен сценарий конфигуратора для Unix dim_ping_benchmark.sh (до этого был только конфигуратор для Windows). Также доработана утилита конфигуратора dim_benchmark.lm9 для работы под Unix. Теперь конфигурация demo_dim_ping полностью функциональна в обоих системах.
Исправлена ошибка в обработке внешних команд, посылаемых утилитой send2crwdaq. Ошибка состояла в “склеивании” в одну строку сообщений, посланных одно за другим с малым интервалом времени. Проверка и вставка EOL в конце сообщения исправило ситуацию (вызов ValidateEol(arg,1)).
Также обновлены библиотеки DieselPascal (инсталлятор install-daqgroup-diesel-ext.run). Там добавлена функция EnsureEndingEol(s) как раз для проверки/вставки EOL в конце строки. Исправлена функция Send2CrwDaq - она не работала под Windows в новой версии crwdaq.
Добавлены отладочные каналы журналирования DebugLog:
_SocketPipe - канал сообщений для
соединений TCP. Этот канал
журналирует критически важные события (создание сокета, соединение,
разрыв связи, закрытие сокета) в каналах связи
TSocketPipe. Трафик данных (пока) не журналируется,
т.к. (пока) не очевидна потребность этого. Журналирование событий
TCP может помочь в установлении причин проблем со
связью.
_UartPort - канал сообщений для
COM портов UART. Этот канал
журналирует критически важные события (открытие порта, закрытие) для
COM портов. Трафик данных (пока) не журналируется, т.к.
(пока) не очевидна потребность этого. Журналирование событий
UART может помочь в установлении причин проблем со
связью.
_SharedMem - канал сообщений для
объектов общей памяти TSharedMemory. Этот
канал журналирует критически важные события (подключение, отключение)
для объектов общей памяти. Трафик данных не журналируется, т.к. для
оперативной памяти это просто нереально.
_NamedPipe - канал сообщений для
соединений именованных каналов Pipe. Этот канал
журналирует критически важные события (создание канала, соединение,
разрыв связи, закрытие канала) в именованных каналах связи
TPipe. В разных системах эти каналы реализованы
по-разному, но выполняют одну и ту же функцию. Пож
Windows это NamedPipe, под
Unix - это UNIX Socket. Трафик данных
(пока) не журналируется, т.к. (пока) не очевидна потребность этого.
Журналирование событий Pipe может помочь в установлении
причин проблем со связью.
Хотя указанные каналы DebugLog не журналируют потоки данных (которые могут быть слишком большими), они полезны для первичного анализа проблем с соединениями - по крайней мере, можно будет увидеть, какие порты открываются или не открываются и почему рвется связь.
Таким образом, теперь в DebugLog журналируются все основные объекты IPC (межпроцессного взаимодействия).
Добавлен модуль _crw_dbglog.pas, содержащий библиотеку отладочного журналирования DebugLog API.
DebugLog API - библиотека функций управляемого отладочного вывода (debug log). Отладочный вывод еще называют журналированием или аудитом. Функция DebugLog, Get/SetDebugLogMode и другие служат для УПРАВЛЯЕМОГО вывода отладочных сообщений, разделенных на КАНАЛЫ (типы сообщений), которые имеют постоянное ИМЯ (Name), динамический (постоянный в рамках сеанса) номер (id), РЕЖИМ вывода (Mode). Отличие от вывода с помощью Echo, DebugOut, writeln … состоит в том, что каналы отладочного вывода DebugLog можно динамически включать/отключать/перенаправлять, во время исполнения При этом всегда сохраняется возможность отладки, но это происходит без потери производительности в случае, если отладка не нужна (отключена).
Правила использования DebugLog в коде Free Pascal:
Подключаем модуль _crw_dbglog в
uses.
В начале программы (например, в секции
initialization) надо зарегистрировать канал отладочного
вывода по имени:
id:=RegisterDebugLogChannel('ChannelName');
Идентификатор канала (id) - следует запомнить.
Идентификатор (id=-1) считается ПРИЗНАКОМ
ОШИБКИ.
Имя канала должно быть идентификатором, как в Pascal.
Надо задать режим (mode) отладочного вывода для канала, например:
SetDebugLogMode(id,0); // Вывод ОТКЛЮЧЕН (по умолчанию)SetDebugLogMode(id,1); // Вывод в консоль с помощью EchoSetDebugLogMode(id,2); // Вывод в файл …/debug.log через DebugOut(…)В цикле опроса/выполнения можно делать отладочные выводы,
например:
if DebugLogEnabled(id) then DebugLog(id,…);
Использование
if DebugLogEnabled(id) позволяет ускорить
выполнение путем БЫСТРОЙ проверки режима вывода.
Отключенный вывод игнорируется.
Вызов DebugLog(id,…) направляет отладочные
сообщения в тот или иной поток вывода в соответствии с режимом вывода
GetDebugLogMode(id).
Флаги режима dlm_XXXX управляют
способом вывода и форматирования. Например, можно отключить метку
времени, вывод миллисекунд времени, вывод имени канала, или выводить
время как число миллисекунд от н.э.
Типичный вывод сообщения (Message) выглядит примерно так:
2024.05.17-09:01:22.328 : ChannelName => Message
С помощью флагов dlm_XXXX можно управлять форматом
(меткой времени, форматом времени, наличием имени).
DebugLog можно безопасно применять в
многопоточной среде.
Однако вызовы Find/RegisterDebugLogChannel желательно
делать при старте программы в основном потоке и далее использовать
полученный при вызове идентификатор канала
(id).
Удаление каналов отладочного вывода не предусмотрено, инициализация делается на все время работы программы. Емкость каналов (DebugLogCapacity) достаточна для большинства задач при разумном (обоснованном) применении каналов отладки.
С помощью DebugLog API добавлены отладочные сообщения по каналам:
_RunCommand - канал сообщений для
вызовов команд операционной системы
RunCommand.
_TaskRun - канал сообщений при
запуске процессов task_run.
_TaskKill - канал сообщений при
прерывании (досрочном завершении) процессов
task_kill.
_ExecuteDPC - канал сообщений для
выполненения отложенных процедурных вызовов
(DeferredProcedureCall), через которые работают команды
WinDraw, WinShow,
WinHide, WinSelect и им
подобные.
Эти отладочные сообщения “зашиты” в код пакетв (в библиотеку crwlib) и являются в этом смысле системными.
Для подобного рода системных (входящих в код пакета) отладочных сообщений принято правило, по которому:
Имена системных каналов отладки DebugLog начинаются со знака
_подчеркивания.
Это правило позволит отделять системные отладочнные сообщения от прикладных, создаваемых прикладными программистами или программами во время работы пакета.
В интерпретатор DaqScript добавлены отладочные команды и функции:
n=@newdebuglog name # регистрация отладочного канала с именем name
debuglogmode(n,1) # задание режима вывода отладочного канала n
debuglogmode(n,_nan) # чтение режима вывода отладочного канала n
debugloglist(0) # число зарегистрированных каналов отладки
debugloglist(1) # список зарегистрированных каналов отладки
debuglogenabled(n) # статус разрешения отладочного вывода в канал n
@debuglog %n message # отладочный вывод сообщения message в канал nНапример, можно делать примерно такие сценарии:
n=@newdebuglog TestDemoDebugLog
debuglogmode(n,1)
@if debuglogenabled(n) then @debuglog %n Отладочный выводПоскольку команды @newdebuglog, @debuglog, debuglogmode, debugloglist, debuglogenabled добавлены в основной (базовый) интерпретатор, они доступны в функции eval. Это позволяет делать отладочный вывод из DaqPascal:
id:=round(eval('@newdebuglog DemoTest'));
rNul(eval('debuglogmode('+str(id)+',1)'));
if (eval('debuglogenabled('+str(id)+')')>0)
then rNul(eval('@debuglog '+str(id)+' Отладочное сообщение'));Не очень красиво, но работать должно. Самое важное здесь то, что такие сообщения легко можно выключать/выключать из консоли или программно. В то же время при отключении они не будут сильно обременять прикладную программу излишней нагрузкой, т.к. при отключении канала вывод игнорируется.
Также для тестирования добавлена команда
@TestBench DemoDebugLog, которая просто
проверяет работу функций DebugLog с выводом в
Главную Консоль.
В окне Консоль Монитора Ресурсов в разделе Windows Messages добавлены счетчики:
Сделаны исправления в команде
@view min/max/norm ….
При переходе с MDI на SDI интерфейс
появилась вероятность, что окно при изменении состояния командой
@view
не будет прорисовано, если оно было невидимым (Visible=false).
Теперь окно должно гарантированно прорисовываться.
Сделаны исправления в окне
DAQ система
(DaqControlDialog).
При переходе с MDI на SDI интерфейс
появилась возможность, что ряд действий, вызываемых по команде
@menu run …, не будут выполняться (т.к.
запрещены), если окно DaqControlDialog закрыто
(спрятано). Это проявлялось в том, например, что многие команды (запрос
статуса DAQ, перезагрузка *DAQ и т.д.)
срабатывали не всегда.
Теперь эти команды разрешаются независимо от состояния окна
DaqControlDialog и должны работать корректно.
Переведена на новую версию пакета демо-конфигурация demo_mayak.
Это драйвер радиометра БДГБ-14И производства ПО
МАЯК на шине MODBUS c полноценным
симулятором.
Переведена на новую версию пакета демо-конфигурация demo_em2rs.
Это драйвер шагового двигателя EM2RS на шине
MODBUS c полноценным симулятором.
Создано А.Жируновым. Мелкие правки А.Курякина.
Добавлена новая команда @colorinfo
в Главной Консоли:
@colorinfo -l - список цветовых констант
@colorinfo -t - вызов таблицы цветовых констант HTML
@colorinfo silver - информация об именованном цвете (silver)
@colorinfo $C4A1A1 - информация о цвете, заданном числом ($C4A1A1)
# Пример вызова:
@colorinfo azure
Azure = $FFFFF0 = #F0FFFF = 16777200 = RGB(240,255,255)
@colorinfo $c1a4a4
Цвет $c1a4a4 = $C1A4A4 = #A4A4C1 = 12690596 = RGB(164,164,193)
Ближайший известный именованный цвет:
LightSteelBlue3 = $CDB5A2 = #A2B5CD = 13481378 = RGB(162,181,205)
# Цвет выдается в виде
# Имени ( LightSteelBlue3 )
# HEX числа ( $CDB5A2 = $GGBBRR )
# Web числа ( #A2B5CD = #RRGGBB )
# десятичное ( 13481378 )
# RGB ( RGB(162,181,205) )@colorfind в
DaqScript:c=@colorfind $c1a4a4
@echo Ближайший известный именованный цвет: %c
@colorinfo %cЭта функция возвращает код ближайшего именованного цвета из таблицы цветов.
Функции @colorinfo,
@colorfind полезны для работы с
цветами.
Например, при создании мнемосхем часто используются именованные
цвета.
Функции позволяют найти имя ближайшего цвета по его RGB
коду.
Переведена на новую версию демо-конфигурация demo_hart для драйвера протокола HART.
Написан файл справки crwdaq-cross.htm по кроссплатформенному программированию и переводу конфигураций из-под старой версии пакета Crw32 в новую версию пакета crwdaq.
Исправлены некоторые мелкие ошибки.
Заведен новый файл справки crwdaq.htm и файл новостей crwdaq-news.htm, в котором будут
делаться записи о новой версии пакета crwdaq.
Старые новости пакета crw32
будут доступны в файле crw-daq-news.htm.
Переведена конфигурация demo_zupdc и demo_gendc.
В пакет crwkit (под Unix) добавлены утилиты для работы с окнами.
unix findwindow # найти окно с заданными параметрами
unix showwindow # показать окно
unix hidewindow # спрятать окно
unix listwindow # напечатать список окон
unix movewindow # сдвинуть окно или изменить размер
unix killwindow # убить окно (убить его процесс)
unix closewindow # закрыть окно (закрыть X клиента)
unix minimizewindow # свернуть окно
unix maximizewindow # развернуть на весь экран
unix setforegroundwindow # активизировать окно
# В качестве аргумента в командах для идентификации окон используется
# заголовок окна, имя класса, имя программы и идентификатор процесса.
# Это позволяет достаточно надежно идентифицировать нужные окна.
# Например:
unix setforegroundwindow 'KCalc'
unix closewindow 'KCalc' 'kcalc.kcalc' 'kcalc'
unix showwindow 'crwdaq-news.md — Kate' 'kate.kate' 'kate'CrwDaq Copyright © 2001-2024 Alexey Kuryakin daqgroup@mail.ru