自定义Engee支持包.综合服务
| 页面进行中。 | 
子系统 恩吉。综合服务 允许您使用客户端程序和硬件支持包组织*Engee*与外部设备之间的交互。
您可以通过扩展*Engee子系统的功能来创建自己的自定义支持包。整合*。 支持包是在客户端程序上运行并将结果返回给*Engee*的Python模块。
使*Engee子系统。集成*接受自定义包,Engee*自动为它们生成Julia语言的代码。 这允许您直接从 命令行*Engee  或者从街区。
 或者从街区。
技术是这一机制的核心。 RPC(远程过程调用)。 您在Julia中调用一个函数,该函数通过网络将参数发送到客户端计算机。 在那里,您的支持包使用这些参数执行相应的Python函数,并将结果返回给*Engee*。
执行架构
了解代码执行的分布很重要:
- 
Python代码--在客户端程序过程中直接在用户计算机上执行; 
- 
Julia代码--在*Engee*子系统中运行并协调交互。 
例如,当调用:
using Main.EngeeDeviceManager.Devices.EXTDEVICE
device = EXTDEVICE.Extdevice()
device.function()Julia代码在*Engee*子系统中执行,Python是一个函数 功能() 它在客户端计算机上执行,其结果返回给*Engee*。
可用的Python包
在开发自定义支持包时,您可以使用所有标准Python包以及以下第三方包:
可用Python包列表
| 包裹 | 资料描述 | 
|---|---|
| aiohttp | 异步HTTP客户端/服务器框架(asyncio) | 
| 自动闪光 | 删除未使用的导入和变量 | 
| 强盗 | 静态Python代码安全分析器 | 
| [医]贝特型 | 运行时快速混合类型检查 | 
| 黑色 | 一个不妥协的代码格式化程序 | 
| 证明;证明 | Mozilla的CA捆绑包 | 
| cffi | 从Python调用C代码的外部函数接口 | 
| doc格式,doc格式 | 根据PEP257格式化文档字符串 | 
| 高射炮8 | 模块化源代码检查器:pep8pyflakes和其他 | 
| gpib-ctypes | PYTHON的GPIB接口,使用ctypes实现 | 
| 隐藏 | Hidapi的Ctypes绑定 | 
| httpx | 下一代HTTP客户端 | 
| intelhex | 用于操作英特尔十六进制文件的Python库 | 
| 伊斯特 | 用于排序Python导入的实用程序/库 | 
| jinja2 | 一个非常快速和富有表现力的模板引擎 | 
| jupyter-客户端 | Jupyter协议实现和客户端库 | 
| jupyter-核心 | Jupyter基本包 | 
| jwcrypto的 | JOSE Web标准的实施 | 
| mdurl | 标记URL实用程序 | 
| 味精背包 | MessagePack序列化器 | 
| 多区 | 多领域的实施 | 
| n.麻木,麻木 | Python中计算数组的基本包 | 
| 有序集 | 记住其顺序的OrderedSet | 
| n.贴片,贴片 | 用于更改动态链接器和RPATH ELF可执行文件的实用程序 | 
| 路径规格 | 用于匹配gitignore样式中的文件路径的实用程序 | 
| 平台,平台 | 确定合适的平台特定目录 | 
| [医]疯狂 | 使用Python类型提示进行数据验证 | 
| 大西洋-核心 | Pydantic验证和序列化的主要功能 | 
| pydantic-设置 | 使用Pydantic管理设置 | 
| [医]皮杜诺克利 | Arduino-cli周围的包装器 | 
| [医]火烧 | 被动Python程序检查器 | 
| [医]皮莫德总线 | Python中的全功能Modbus协议栈 | 
| [医]皮塞里亚 | Python串口扩展 | 
| [医]皮乌斯布 | 来自Python的USB访问模块 | 
| [医]皮维萨 | Gpib、RS232、TCPIP和USB工具的PYTHON VISA绑定 | 
| 皮维萨-py | VISA库的纯Python实现 | 
| [医]皮亚姆 | Python的YAML解析器和发射器 | 
| [医]pyzmq | 0mq的Python绑定 | 
| n.redis | 用于Redis数据库和键值存储的Python客户端 | 
| 请求 | Python中人的HTTP | 
| 设置工具 | 轻松下载、构建、安装、更新和删除Python包。 | 
| 汤姆尔 | Python库为汤姆的明显,最小的语言 | 
| 鹿untokenize | 将令牌转换为源代码(同时保留空格) | 
| urllib3 | 具有线程安全连接池的HTTP库,文件发送等。 | 
创建多文件支持包的示例
| 为了您的方便,我们准备了 存档与完成的项目结构和代码示例。 您将在存档中找到完整的文件夹结构。 设备和目标与工作的例子。 | 
让我们用我们自己的文件层次结构创建一个支持包。 为此,我们使用模板文件夹。 模块,里面有目录 设备 和 目标.
- 
*Device*是*不*与*Engee*模型交互并且不使用其数据的任意用户类。 
- 
Target*是一个用户类,它*与*Engee*模型交互,从中接收数据进行处理,并在另一个平台(微控制器,独立计算机等)上执行。). 
在我们的示例中,我们将创建一个具有多文件结构的*device*。
- 
在文件夹中创建 设备一个新文件夹外接/外接.
- 
里面 外接/外接创建文件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在同一文件夹中外接/外接:
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.info ("讯息")--资讯讯息;
- 
伐木工人。警告("讯息")--警告;
- 
伐木工人。错误("讯息")--错误。
消息将显示在日志面板中客户端程序的图形界面中。 您还可以在上面附加的存档中找到日志记录使用的示例。
注册和使用Engee支持包
| 在注册之前,请确保您的文件夹结构与存档中的示例匹配。 | 
创建支持包后,您需要在Julia上生成相应的代码,并在*Engee*中注册该包。
首先,让我们来看看现有设备的列表。:
engee> using Main.EngeeDeviceManager.Devices.
可以COM回声HID
HTTP L502BOARD LOGITECHG29WHEEL MODBUSMASTER
套接字TFLEXDOCS THRUSTMASTERJOYSTICK THRUSTMASTERTHROTTLE
UM UTILS签证我们的支援计划 外接/外接 还没到。
我们将指定我们的文件夹的路径 模块 并下载包(有关下面使用的方法的更多信息,请参阅文章 使用文件系统和支持包的软件管理):
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现在支持包 外接/外接 在列表中,它可以使用:
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)| 功能 删除,删除从启动列表中删除支持包。 要使更改生效,必须完全重新启动*Engee子系统。整合*。 | 
因此,我们在*Engee*和自定义Python代码之间创建了一个"桥梁",在客户端程序上执行计算并在*Engee*中获得结果。