Прошло уже достаточно времени с публикации моей предыдущей статьи. За это время я значительно улучшил приложение. Миграция проекта с WPF на Avalonia UI, обновленный дизайн, работа с числами типа float, а также другие возможности появились в новой версии моего Modbus терминала.

Начнем с главного. Теперь программа работает и под Windows, и под Linux. Windows версия распространяется как обернутой в инсталлер, так и portable. А Linux версия обычным zip-архивом.

Основные нововведения:

  • Проект перенесен с WPF на AvaloniaUI.

  • Изменен дизайн.

  • Добавлен Modbus сканер.

  • Modbus: для каждой функции записи сделан свой вариант дизайна.

  • Modbus: добавлено ведение истории обмена.

  • Modbus: добавлена возможность работы с бинарными данными.

  • Modbus: добавлена возможность работы с данными типа float.

  • Исправлены ошибки версии 2.7.0.

Ссылки для скачивания вы можете найти в конце статьи. Но не спешите перематывать :) Советую сначала ознакомиться с материалом ниже.

Инструкция

Для режима работы "Без протокола", думаю, пояснения не нужны. Он работает как текстовый терминал. Просто и пока без изысков.

Из прошлой версии приложения перекочевали два способа взаимодействия с хостом: "Обычный" и "Цикличный опрос". Между ними можно переключаться во время работы. Данные на вкладках не теряются при переключении.

Важно: если переключиться в обычный режим пока идет цикличный опрос, то сам опрос прекратится.

Версия для режима "Без протокола":

"Без протокола" - Обычный режим работы
"Без протокола" - Обычный режим работы
"Без протокола" - Режим цикличного опроса
"Без протокола" - Режим цикличного опроса

Версия для режима Modbus:

Modbus - Обычный режим работы
Modbus - Обычный режим работы
Modbus - Режим цикличного опроса
Modbus - Режим цикличного опроса

Теперь давайте поподробнее рассмотрим обычный режим работы Modbus. В этом режиме все сводится к чтению и записи регистров.

Чтение регистров Modbus

С чтением все просто. Выбираем функцию, начальный адрес, количество регистров и нажимаем кнопку «Прочитать»

Запись регистров Modbus

С записью все интереснее. Для каждой функции предусмотрен свой вариант дизайна.

Начальным адресом для всех функций является значение из поля «Адрес».

0x05 Запись одного флага

Согласно документации на протокол, в поле данных должно находится только одно из двух значений. 0x0000 – это логический ноль, а 0xFF00 – это логическая единица. Поэтому выбираем желаемое значение и нажимаем кнопку «Записать».

0x0F Запись нескольких флагов

Похожая функция, но в отличии от предыдущей позволяет записать сразу несколько флагов. С помощью кнопки «Добавить регистр» создаем нужное количество флагов, задаем значение и нажимаем кнопку «Записать».

Слева от значений регистров у нас находятся значения смещения относительно начального адреса.

Справа находятся кнопки удаления для каждого регистра.

0x06 Запись одного регистра

С помощью этой функции мы можем записывать в 16-ти разрядные регистры.

Формат записываемого числа выбирается в выпадающем списке справа от поля ввода. При смене формата число автоматически преобразуется.

0x10 Запись нескольких регистров

Управление тут аналогично функции «0x0F Запись нескольких флагов».

Из интересного у нас появляется возможность записи чисел типа float.

Как мы знаем такие числа занимают 2 слова или же 4 байта. Поэтому у следующего регистра смещение уже не +1, а +2 адреса.

Иногда бывает, что устройство может использовать нетипичный формат для расшифровки чисел типа float. И чтобы подстроиться под конкретное устройство в настройках можно выбрать нужный формат записи.

Представления

Просто значения регистров можно посмотреть в табличном представлении. Но, к сожалению, в этих числах не всегда есть смысл. И иногда их требуется "расшифровать". Поэтому для интерпретации данных в терминале предусмотрена область с представлениями.

Первым идет представление последнего запроса. Тут можно увидеть просто байты запроса и ответа. Это удобно использовать, например, когда идет отладка устройства с самодельной реализацией протокола. Или же когда полученный результат показался сомнительным, и хочется посмотреть детали обмена.

Представление последнего запроса
Представление последнего запроса

Название следующего представления говорит само за себя. Из интересного можно отметить разве только время отправки запроса / получения ответа. Иногда бывает полезно посмотреть при подключении по последовательному порту.

Представление истории обмена
Представление истории обмена

Бинарное представление в основном нужно для удобной работы с масками. А чтобы в конце рабочего дня единицы не сливались с нулями, я решил помимо группировки, разделить биты цветом, в зависимости от их значения.

Бинарное представление
Бинарное представление

И пожалуй, пока что самое полезное представление - это представление числа типа float. Для каждых двух слов представлены все комбинации. Если же среди всех четырех вариантов не нашлось "нормального" числа (например, как в 4 адресе), то скорее всего эта пара слов не содержит float числа или же оно вот такое странное.

Представление числа типа float
Представление числа типа float

При интерпретации результатов не стоит обделять вниманием табличное представление. Иногда, в совокупности с остальными, оно может дать больше полезной информации.

Немного о разработке

С точки зрения кода основное нововведение это миграция проекта с WPF на Avalonia UI.

Вот основные причины на это:

  • Кроссплатформенность. Это, пожалуй, самая главная причина :) Программа теперь запускается на Windows и Linux.

  • Современный дизайн и гибкость. Из коробки нам доступна тема Fluent, которая выглядит эстетично и современно. В сети можно найти и другие темы, что позволяет нам делать красивый дизайн. Также встроенные контролы имеют более широкие настройки. Например, чтобы сделать кнопку со скругленными краями в WPF мне пришлось переопределять шаблон кнопки, а в Avalonia UI я просто задал CornerRadius у самой кнопки.

  • Возможности стилизации. В Avalonia UI используются CSS-подобные селекторы. Сразу после перехода с WPF это довольно непривычно, но со временем оказывается, что применение таких селекторов очень удобно. С помощью них, можно создавать типовые стили для контролов.

  • Меньший размер проекта. Приведу небольшое сравнение версий для Windows.

    • Версия 2.7.0 WPF: инсталлер - 47 Мб, на диске - 160 Мб.

    • Версия 3.0.0 Avalonia UI: инсталлер - 32 Мб, на диске - 103 Мб.

  • Живое сообщество. Avalonia UI активно развивается сообществом. В проект добавляется новый функционал, правятся баги. Ознакомится с проектом можно в репозитории на GitHub, а попросить помощи или просто обсудить можно в русскоязычном чате в Telegram.

Далее хочу поделиться личным опытом переноса проектов с WPF на Avalonia UI.

Для начала нужно понять насколько проект большой. Если он состоит из пары полей ввода и одной кнопки, то дальше можно не читать :) Ну а если у вас все сложнее, то первым делом необходимо переписать проект согласно паттерну MVVM... Да, я понимаю, что это может быть сложно, но без этого мигрировать проект и развивать его дальше будет еще сложнее. Поэтому из двух зол выбираем меньшее.

Для успешной миграции нам нужно заранее выделить всё что связанно с WPF в отдельные проекты.

Важно отметить, что в Avalonia нет стандартного MessageBox, как в WPF. Поэтому логику работы с ним тоже выносим в отдельный проект. Или же, как вариант, можно найти реализацию MessageBox на GitHub.

Следующим шагом мы просто удаляем все проекты с WPF. В том числе и из папки с решением.

Теперь собираем решение. Если все прошло успешно, то это значит, что у нас нет лишних зависимостей, и мы все сделали правильно.

Далее добавляем новый проект Avalonia UI в свое решение. Проводим стандартные манипуляции. Не забываем проверить версию .NET во всех проектах, а также удалить теперь ненужные NuGet пакеты связанные с WPF. Например, ReactiveUI.WPF заменяем на Avalonia.ReactiveUI.

Теперь выбираем в качестве запускаемого проект Desktop (моем случае это TerminalProgram.Desktop) и запускаем его. Появляется окошко. Ура! Мы все сделали правильно.

Настала очередь переноса UI. Важно помнить, что некоторые контролы из WPF отсутствуют в Avalonia UI. Но как правило можно найти аналог. Например, вместо Frame и Page можно использовать ContentControl и UserControl соответственно.

Также приведу несколько полезных ссылок:

Как уже было написано выше, Avalonia активно развивается сообществом. Важно понимать, что это сравнительно молодой GUI фреймворк. Поэтому в нем можно наткнуться на баги. Чаще всего они не доставляют проблем, но бывают и исключения.

Приведу пример. Я хотел, чтобы мое приложение выглядело одинаково на всех ОС. Поэтому мне пришлось сделать свой вариант окна. В Avalonia есть классная возможность отключить неклиентскую часть окна (WindowChrome). Но при этом оставить его границы, с помощью которых можно масштабировать окно (SystemDecorations="BorderOnly"). В версии 11.2.0 эта функция замечательно себя чувствует на Windows 10/11, и совершенно отказывается работать на дистрибутивах Linux и внезапно на Windows 7. Это не критичный баг. Но он хорошо иллюстрирует, что на них можно наткнуться при разработке. Надеюсь, его исправят в ближайших обновлениях.

В своем приложении я решил просто создать аналог ResizeGrip из WPF.

Вообще для разработки кастомных окон вам будут полезны два метода класса Window:

  • BeginMoveDrag(PointerPressedEventArgs e) - для перетаскивания окна вслед за курсором мыши.

  • BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e) - для масштабирования окна вслед за курсором мыши.

Читая этот раздел, у вас может возникнуть вопрос: «А что же в итоге выбрать — Avalonia UI или WPF?» «Все зависит от задачи», — отвечу я вам. Если вам нужна кроссплатформенность, гибкость, красивый дизайн, и вы готовы мериться с редкими небольшими багами, то смотрите в сторону Avalonia UI. А если же у вас корпоративный софт на Windows машинах с дизайном "чтобы просто было", то может проще использовать Windows Forms? :)

Итого

Версия приложения 3.0.0 писалась довольно долго. Основные фичи этого обновления - это все же добавление кроссплатформенности и новый дизайн. Также я прислушался к пожеланиям пользователей в комментариях к предыдущей статье. Часть из них совпадали с моими пожеланиями и возможностями. Что и вылилось в новую версию терминала. Надеюсь, вам понравилось мое приложение. Буду рад обратной связи в комментариях.

Приложение тестировалось на Windows 10/11, Ubuntu и Astra Linux.

Смотрите также:

Терминал Modbus TCP / RTU / ASCII с открытым исходным кодом: Часть 1

Комментарии (4)


  1. AngryPinguin
    15.11.2024 10:51

    А не пробовали на андроиде запустить? Авалония просто это вроде как позволяет.


    1. AndreyAbdulkayumov Автор
      15.11.2024 10:51

      Нет, не пробовал) Я проектировал дизайн под десктоп. На мобильных устройствах будет мелковато.


      1. checkpoint
        15.11.2024 10:51

        Под FreeBSD можете собрать ? Готов потестировать. :)


        1. AndreyAbdulkayumov Автор
          15.11.2024 10:51

          К сожалению, под FreeBSD собрать не получится. Ни Avalonia, ни .NET официально не поддерживают эту ОС. И при разработке я все же ориентировался на версии только для Windows/Linux.

          Но вы можете попробовать это сделать сами :) Код лежит в свободном доступе.