Документация Engee

Создание и использование пользовательских расширений через пакет поддержки оборудования Engee

Страница в процессе разработки.

Пакет поддержки оборудования Engee позволяет организовать взаимодействие между Engee и клиентской программой пользователя.

Теперь вы можете создавать собственные модули на Python, которые будут выполняться на клиентской программе и возвращать результат обратно в Engee. Для этого предусмотрена автоматическая генерация Julia-кода из ваших Python-модулей. Это позволяет вызывать ваши функции прямо из командной строки Engee или из блоков.

В основе этого механизма лежит технология RPC (Remote Procedure Call — удаленный вызов процедур). Вы вызываете функцию в Julia, которая отправляет аргументы по сети на клиентский компьютер. Там пакет поддержки оборудования выполняет соответствующую Python-функцию с этими параметрами и возвращает результат обратно.

Пример создания простого расширения

Давайте создадим простое пользовательское расширение. Для этого используем шаблон — папку module, внутри которой есть директории devices и targets.

  • Девайс (Device) — это произвольный пользовательский класс, который не взаимодействует с моделями Engee и не использует их данные.

  • Таргет (Target) — это пользовательский класс, который взаимодействует с моделью Engee, получает из нее данные для обработки и исполняется на другой платформе (микроконтроллере, отдельном компьютере и т.д.).

В нашем примере мы создадим девайс.

  1. Создадим в папке devices новую папку demo.

  2. Внутри demo создадим файл demo.py со следующим кодом:

import time
import datetime

from devices.base_device import BaseDevice

class Demo(BaseDevice):
    def __init__(self) -> None:
        pass

    def __del__(self) -> None:
        pass

    def solve_equation(self, x: float, y: float, z: float) -> float:
        return x * y - z

    def get_host_time(self) -> str:
        host_time = time.localtime()
        return str(host_time)

Это пример простого девайса. Наш класс Demo может вычислить результат уравнения с заданными параметрами и вернуть текущее время с клиентской программы в Engee.

Обратите внимание, что класс Demo наследуется от BaseDevice. Это необходимо, чтобы пакет поддержки оборудования зарегистрировал его как RPC-класс. Если бы мы создавали таргет, то наследовались бы от BaseTarget:

from targets.base_target import BaseTarget
Для пользовательских RPC-классов обязательно наследование от BaseDevice (если это девайс) или от BaseTarget (если это таргет).

Передача структур данных

Если вы хотите передавать сложные структуры данных, то создайте в той же директории demo файл models.py. Например:

from devices.base_models import BaseModel

class MyStruct(BaseModel):
    parameter_x: int
    parameter_y: int
    parameter_z: float
Для структур данных обязательно наследование от BaseModel!

Затем вы можете использовать эту структуру в своем основном классе:

from devices.demo.models import MyStruct

class Demo(BaseDevice):
    ...
    def func(self, comp_s: MyStruct) -> float:
        return comp_s.parameter_x + comp_s.parameter_y + comp_s.parameter_z

Регистрация и использование модуля в Engee

После создания Python-модуля нужно сгенерировать соответствующий Julia-код и зарегистрировать модуль в Engee.

Сначала посмотрим список существующих девайсов:

engee> using Main.EngeeDeviceManager.Devices.

CAN                   COM                   ECHO                  HID
HTTP                  L502BOARD             LOGITECHG29WHEEL      MODBUSMASTER
SOCKET                TFLEXDOCS             THRUSTMASTERJOYSTICK  THRUSTMASTERTHROTTLE
UM                    UTILS                 VISA

Нашего модуля DEMO здесь еще нет.

Укажем путь к нашей папке 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!

Теперь модуль зарегистрирован. Перезагрузим ядро Engee и перезапустим пакет поддержки оборудования:

engee> engee.clear_all()
# Ждем перезагрузки ядра
engee> engee.package.start("Engee-Device-Manager")

Снова посмотрим список девайсов:

engee> using Main.EngeeDeviceManager.Devices.

CAN                   COM                   DEMO                  ECHO
HID                   HTTP                  L502BOARD             LOGITECHG29WHEEL
MODBUSMASTER          SOCKET                TFLEXDOCS             THRUSTMASTERJOYSTICK
THRUSTMASTERTHROTTLE  UM                    UTILS                 VISA

Теперь модуль DEMO в списке и его можно использовать:

engee> demo = DEMO.Demo()
Main.EngeeDeviceManager.Devices.DEMO.Demo("Demo", UUID("1ffb2334-3176-42ac-931e-c278af2506cb"), ["solve_equation", "get_host_time"], "Demo_1ffb2334-3176-42ac-931e-c278af2506cb_reply", Main.EngeeDeviceManager.Devices.DEMO.var"#solve_equation#3"{String, UUID}("Demo", UUID("1ffb2334-3176-42ac-931e-c278af2506cb")), Main.EngeeDeviceManager.Devices.DEMO.var"#get_host_time#4"{String, UUID}("Demo", UUID("1ffb2334-3176-42ac-931e-c278af2506cb")))

engee> demo.solve_equation(5.5, 6.6, 7.7)
28.599999999999998

engee> demo.get_host_time()
"time.struct_time(tm_year=2025, tm_mon=8, tm_mday=27, tm_hour=19, tm_min=32, tm_sec=52, tm_wday=2, tm_yday=239, tm_isdst=0)"

Ваше расширение будет автоматически загружаться при каждом запуске клиентской программы. Если оно больше не нужно, то его можно удалить из автозагрузки:

engee> UTILS_API.deleteExtension(utils, module_path)
Функция deleteExtension удаляет расширение из списка автозагрузки. Чтобы изменения вступили в силу, необходимо полностью перезапустить пакет поддержки оборудования Engee.

Таким образом, мы создали «мост» между Engee и пользовательским кодом на Python, выполнили вычисления на клиентской программе и получили результат в Engee.