Пользовательские пакеты поддержки Engee.Интеграции
|
Страница в процессе разработки. |
Подсистема Engee.Интеграции позволяет организовать взаимодействие между Engee и внешним оборудованием с помощью клиентской программы и пакетов поддержки оборудования.
Вы можете создавать свои собственные пользовательские пакеты поддержки, расширяя функциональность подсистемы Engee.Интеграции. Пакет поддержки представляет собой модуль на языке Python, который исполняется на клиентской программе и возвращает результат обратно в Engee.
Чтобы подсистема Engee.Интеграции принимала пользовательские пакеты, Engee автоматически генерирует для них код на языке Julia. Это позволяет вызывать ваши функции прямо из командной строки Engee
или из блоков.
В основе этого механизма лежит технология RPC (Remote Procedure Call — удаленный вызов процедур). Вы вызываете функцию в Julia, которая отправляет аргументы по сети на клиентский компьютер. Там ваш пакет поддержки выполняет соответствующую Python-функцию с этими параметрами и возвращает результат обратно в Engee.
Архитектура выполнения
Важно понимать распределение выполнения кода:
-
Код на Python — выполняется непосредственно на компьютере пользователя в процессе клиентской программы;
-
Код на Julia — выполняется в подсистеме Engee и координирует взаимодействие.
Например, при вызове:
using Main.EngeeDeviceManager.Devices.EXTDEVICE
device = EXTDEVICE.Extdevice()
device.function()
Julia-код выполняется в подсистеме Engee, а Python-функция function() выполняется на клиентском компьютере, и ее результат возвращается в Engee.
Доступные пакеты Python
При разработке пользовательских пакетов поддержки вам доступны все стандартные пакеты Python, а также следующие сторонние пакеты:
Список доступных пакетов Python
| Пакет | Описание |
|---|---|
aiohttp |
Асинхронный HTTP клиент/сервер фреймворк (asyncio) |
autoflake |
Удаляет неиспользуемые импорты и переменные |
bandit |
Статический анализатор безопасности Python кода |
beartype |
Быстрая гибридная проверка типов во время выполнения |
black |
Бескомпромиссный форматировщик кода |
certifi |
Пакет для предоставления Mozilla’s CA Bundle |
cffi |
Интерфейс внешних функций для вызова Си кода из Python |
docformatter |
Форматирует строки документации в соответствии с PEP 257 |
flake8 |
Модульный проверщик исходного кода: pep8 pyflakes и другие |
gpib-ctypes |
Интерфейс GPIB для Python, реализованный с использованием ctypes |
hid |
Привязки ctypes для hidapi |
httpx |
HTTP клиент следующего поколения |
intelhex |
Библиотека Python для манипуляций с файлами Intel HEX |
isort |
Утилита/библиотека для сортировки импортов Python |
jinja2 |
Очень быстрый и выразительный шаблонизатор |
jupyter-client |
Реализация протокола Jupyter и клиентские библиотеки |
jupyter-core |
Основной пакет Jupyter |
jwcrypto |
Реализация стандартов JOSE Web |
mdurl |
Утилиты для URL Markdown |
msgpack |
Сериализатор MessagePack |
multidict |
Реализация multidict |
numpy |
Фундаментальный пакет для вычислений с массивами в Python |
ordered-set |
OrderedSet, который запоминает свой порядок |
patchelf |
Утилита для изменения динамического linker и RPATH ELF исполняемых файлов |
pathspec |
Утилита для сопоставления путей файлов в стиле gitignore |
platformdirs |
Определение подходящих платформо-специфичных директорий |
pydantic |
Валидация данных с использованием подсказок типов Python |
pydantic-core |
Основная функциональность для валидации и сериализации Pydantic |
pydantic-settings |
Управление настройками с использованием Pydantic |
pyduinocli |
Обертка вокруг arduino-cli |
pyflakes |
Пассивный проверщик Python программ |
pymodbus |
Полнофункциональный стек протокола Modbus на python |
pyserial |
Расширение для последовательного порта Python |
pyusb |
Модуль доступа к USB из Python |
pyvisa |
Привязки Python VISA для инструментов GPIB, RS232, TCPIP и USB |
pyvisa-py |
Чистая Python реализация библиотеки VISA |
pyyaml |
Парсер и эмиттер YAML для Python |
pyzmq |
Привязки Python для 0MQ |
redis |
Python клиент для базы данных Redis и key-value хранилища |
requests |
HTTP для людей на Python |
setuptools |
Легко загружайте, собирайте, устанавливайте, обновляйте и удаляйте пакеты Python |
toml |
Библиотека Python для Tom’s Obvious, Minimal Language |
untokenize |
Преобразует токены в исходный код (с сохранением пробелов) |
urllib3 |
HTTP библиотека с потокобезопасным пулом соединений, отправкой файлов и прочее |
Пример создания мультифайлового пакета поддержки
Для вашего удобства мы подготовили архив с готовой структурой проекта и примерами кода. В архиве вы найдете полную структуру папок devices и targets с рабочими примерами.
|
Давайте создадим пакет поддержки с собственной иерархией файлов. Для этого используем шаблон — папку module, внутри которой есть директории devices и targets.
-
Девайс (Device) — это произвольный пользовательский класс, который не взаимодействует с моделями Engee и не использует их данные.
-
Таргет (Target) — это пользовательский класс, который взаимодействует с моделью Engee, получает из нее данные для обработки и исполняется на другой платформе (микроконтроллере, отдельном компьютере и т.д.).
В нашем примере мы создадим девайс с многофайловой структурой.
-
Создадим в папке
devicesновую папкуextdevice. -
Внутри
extdeviceсоздадим файлextdevice.pyсо следующим кодом:
import time
from devices.base_device import BaseDevice
from .models import DeviceConfig, CalculationResult
class Extdevice(BaseDevice):
def __init__(self, device_id: int, calibration_factor: float) -> None:
self.device_id = device_id
self.calibration_factor = calibration_factor
def __del__(self) -> None:
pass
def complex_calculation(self, config: DeviceConfig) -> CalculationResult:
# Сложные вычисления с использованием конфигурации
result_value = (config.parameter_a * config.parameter_b +
config.parameter_c) * self.calibration_factor
return CalculationResult(
success=True,
value=result_value,
timestamp=time.time()
)
def get_status(self) -> str:
return f"Device {self.device_id} operational with factor {self.calibration_factor}"
-
Создадим файл
models.pyв той же папкеextdevice:
from devices.base_models import BaseModel
class DeviceConfig(BaseModel):
parameter_a: float
parameter_b: int
parameter_c: float
class CalculationResult(BaseModel):
success: bool
value: float
timestamp: float
|
Для пользовательских RPC-классов обязательно наследование от Для структур данных обязательно наследование от Все методы должны иметь полные аннотации типов для параметров и возвращаемого значения. Например:
Без аннотаций система не сможет корректно сгенерировать Julia-код и преобразовать типы данных между Python и Julia. |
| Наглядно увидеть, как описанный выше механизм создания собственного пакета поддержки применяется на практике для работы с реальным оборудованием, можно в примере Сообщества: Разработка пакета поддержки оборудования для Engee.Интеграции. |
Отладка пакетов поддержки
Для отладки вашего расширения можно использовать встроенную систему логирования. Добавьте в ваш код:
from main_logger import MainLogger
class Extdevice(BaseDevice):
def __init__(self, device_id: int, calibration_factor: float) -> None:
self.logger = MainLogger()
self.logger.info(f"Initializing device {device_id}")
self.device_id = device_id
self.calibration_factor = calibration_factor
def complex_calculation(self, config: DeviceConfig) -> CalculationResult:
self.logger.debug("Starting complex calculation")
# ... ваш код ...
self.logger.info("Calculation completed successfully")
return result
Доступные уровни логирования:
-
logger.debug("сообщение")— отладочная информация; -
logger.info("сообщение")— информационные сообщения; -
logger.warning("сообщение")— предупреждения; -
logger.error("сообщение")— ошибки.
Сообщения будут отображаться в графическом интерфейсе клиентской программы в панели логов. Примеры использования логирования вы также найдете в приложенном выше архиве.
Регистрация и использование пакета поддержки в Engee
| Перед регистрацией убедитесь, что ваша структура папок соответствует примеру из архива. |
После создания пакета поддержки нужно сгенерировать соответствующий код на Julia и зарегистрировать пакет в Engee.
Сначала посмотрим список существующих девайсов:
engee> using Main.EngeeDeviceManager.Devices.
CAN COM ECHO HID
HTTP L502BOARD LOGITECHG29WHEEL MODBUSMASTER
SOCKET TFLEXDOCS THRUSTMASTERJOYSTICK THRUSTMASTERTHROTTLE
UM UTILS VISA
Нашего пакета поддержки EXTDEVICE здесь еще нет.
Укажем путь к нашей папке module и загрузим пакет (подробнее про используемые далее методы см. статью Программное управление для работы с файловой системой и пакетами поддержки):
engee> module_path = "/path/to/module"
engee> using Main.EngeeDeviceManager.Devices.UTILS
engee> using Main.EngeeDeviceManager.UTILS_API
engee> utils = UTILS.Utils()
engee> UTILS_API.loadExtension(utils, module_path)
Если все прошло успешно, то в логах клиентской программы появится сообщение:
INFO | Extension with name: module was loaded successfully!
|
Процедура обновления пакета поддержки: Если вы изменили только реализацию существующих функций (без изменения сигнатур, типов возврата или имен функций):
Если вы добавили новые функции, классы или модели (наследники BaseModel):
|
Теперь пакет поддержки зарегистрирован. Перезагрузим ядро Engee и перезапустим подсистему Engee.Интеграции:
engee> engee.clear_all()
# Ждем перезагрузки ядра
engee> engee.package.start("Engee-Device-Manager")
Снова посмотрим список девайсов:
engee> using Main.EngeeDeviceManager.Devices.
CAN COM ECHO EXTDEVICE
HID HTTP L502BOARD LOGITECHG29WHEEL
MODBUSMASTER SOCKET TFLEXDOCS THRUSTMASTERJOYSTICK
THRUSTMASTERTHROTTLE UM UTILS VISA
Теперь пакет поддержки EXTDEVICE в списке и его можно использовать:
engee> using Main.EngeeDeviceManager.Devices.EXTDEVICE
engee> device = EXTDEVICE.Extdevice(123, 1.5)
engee> device.get_status()
"Device 123 operational with factor 1.5"
engee> config = EXTDEVICE.DeviceConfig(2.5, 10, 3.14)
engee> result = device.complex_calculation(config)
Ваш пакет поддержки будет автоматически загружаться при каждом запуске клиентской программы. Если он больше не нужен, то его можно удалить из автозагрузки:
engee> UTILS_API.deleteExtension(utils, module_path)
Функция deleteExtension удаляет пакет поддержки из списка автозагрузки. Чтобы изменения вступили в силу, необходимо полностью перезапустить подсистему Engee.Интеграции.
|
Таким образом, мы создали «мост» между Engee и пользовательским кодом на Python, выполнили вычисления на клиентской программе и получили результат в Engee.