开发自定义设备支持包
本指南描述了一个场景,其中:
-
基于Python的自定义支持包在本地计算机上运行,您需要从 AnyMath .
-
还假设该支持包将在模型中使用。 AnyMath 还有他从街区打来的电话 Engee Function.
-
这个任务可以用 恩吉。综合服务.
设备支持包的结构
最小设备模板放在目录中 设备:
my_extension/
devices/
mydevice/
__init__.py
mydevice.py
支持包(设备)必须位于 设备/<设备文件夹>/.
|
命名方案:
devices/debug_device/ — папка устройства
├── __init__.py — from .debug_device import DebugDevice
└── debug_device.py — class DebugDevice(BaseDevice):
def ping(...) -> str:
Julia: EngeeDeviceManager.Devices.DEBUGDEVICE
Блок: using .EngeeDeviceManager.Devices.DEBUGDEVICE
dev = DEBUGDEVICE.DebugDevice()
文件夹名称 debug_device,类名 [医]DebugDevice 和Julia模块的名称 [医]DEBUGDEVICE 受大小写转换规则约束: 蛇类,蛇类 → 骆驼箱 (Python类)→ UPPER_CASE (Julia是一个模块)。
设备类(Python)
强制性要求:
-
继承自
N.基地,基地. -
所有参数类型的完整注释和公共方法的返回值。
-
打算从块调用的方法不应该以
和_-这些方法将无法从脚本和块中获得。
设备类的示例:
from devices.base_device import BaseDevice
from main_logger import MainLogger
class MyDeviceLogger(MainLogger):
pass
logger = MyDeviceLogger()
class MyDevice(BaseDevice):
def __init__(self) -> None:
pass
def connect(self, host: str, port: int) -> bool:
logger.info("Connect {}:{}", host, port)
return True
def read_value(self, channel: int) -> float:
return 12.34
请注意,从内置类继承时 主博客 可以为自定义支持包实现多语言日志记录。 例如:
from collections import defaultdict
from typing import Any
from main_logger import MainLogger
class MyDeviceLogger(MainLogger):
def __init__(self) -> None:
self.tr: Any = defaultdict(dict)
self.tr = {
"Connect {}:{}": {
"ru": "Подключение к {}:{}",
},
"Read failed: {}": {
"ru": "Ошибка чтения: {}",
},
}
| 您可以清楚地看到上面描述的用于开发自己的支持包的机制是如何在实践中应用于使用社区示例的真实硬件的。: 为Engee开发硬件支持包。整合。 |
从Engee功能块调用
在 *Common code*从连接开始 Engee.集成,如在标准 .nglib 街区 硬件,其源代码是开放的。
package_dir = "/internal_persistent_vol/support_packages/locations/Engee-Device-Manager/EngeeDeviceManager.jl"
include("$(package_dir)/src/EngeeDeviceManager.jl")
using .EngeeDeviceManager
using .EngeeDeviceManager.Devices.MYDEVICE
然后使用通常的方法调用。:
mutable struct Block <: AbstractCausalComponent
dev::MYDEVICE.MyDevice
function Block()
d = MYDEVICE.MyDevice()
d.connect(host, Int(port))
new(d)
end
end
function (c::Block)(t::Real, channel)
return c.dev.read_value(Int(channel))
end
这里 梅迪维斯 -这是与类名对应的用户支持包模块的名称 梅迪维斯 大写。
一个包含参数、初始化和完成的块的完整示例
一个典型的设备 UDP RX*用途 *Common code 三个功能:
package_dir = "/internal_persistent_vol/support_packages/locations/Engee-Device-Manager/EngeeDeviceManager.jl"
include("$(package_dir)/src/EngeeDeviceManager.jl")
using .EngeeDeviceManager
using .EngeeDeviceManager.Devices.SOCKET
mutable struct Block <: AbstractCausalComponent
socket::SOCKET.Socket
function Block()
socket = SOCKET.Socket("AF_INET", "SOCK_DGRAM")
SOCKET.bind(socket, ip, port)
new(socket)
end
end
function (c::Block)(t::Real)
response = SOCKET.receive(c.socket, buf_size)
if response === nothing
return 0, zeros(UInt8, buf_size)
elseif length(response.data) == 0
return 0, zeros(UInt8, buf_size)
end
return length(response.data), resize!(response.data, buf_size)
end
function terminate!(c::Block)
SOCKET.close(c.socket)
return nothing
end
分析结构:
-
构造函数
座()-模拟运行时调用一次。 在其中创建设备的实例并调用初始化方法(绑定,打开,连接等等)。 块参数(知识产权,港口)取自掩码,可作为构造函数参数使用。 -
功能
(c::Block)(t::Real)-在模拟的每一步调用。 这是块的主体。 这里t-当前时间,嗯c.领域-访问结构的字段。 返回的值对应于块的输出端口的顺序。 -
功能
终止!(c::座)-在模拟结束时调用。 它释放了资源:关闭套接字,文件和连接。 她的挑战是可选的。
块参数*通过掩码设置(假面价值 在 .nglib). 在 *Common code 从面具上用他们的名字来称呼他们: 知识产权, 港口, buf_大小, 采样时间.
以相同的方式启用自定义支持包。 一开始 Common code 请务必指定模块的路径:
package_dir = "/internal_persistent_vol/support_packages/locations/Engee-Device-Manager/EngeeDeviceManager.jl"
include("$(package_dir)/src/EngeeDeviceManager.jl")
using .EngeeDeviceManager
using .EngeeDeviceManager.Devices.MYDEVICE
mutable struct Block <: AbstractCausalComponent
dev::MYDEVICE.MyDevice
function Block()
d = MYDEVICE.MyDevice()
d.connect(host, port)
new(d)
end
end
function (c::Block)(t::Real)
return c.dev.read_value(channel)
end
function terminate!(c::Block)
# закрытие соединения, если необходимо
return nothing
end