Python API 参考
Darra PnSlave Python SDK(包名暂仍 darra_pnet,本波不改标识符)。产品路径是服务模式:PnetService.connect() 不传 host,映射驱动命名 Section \\Device\\DarraRT_Pnet_GlobalIO,不探测 HTTP、不加载 DarraPnet.dll、不打开 \\.\DarraRT_Pnet(B1 句柄由服务独占)。传 host 才走 HTTP 备用(端口 18840 固定,仅本机回环)。命名用 Python 惯例(snake_case)。
无用户周期。 从站不
tick、不自己跑 PDO 循环。栈周期由服务 / 驱动承载。应用只做:start→ 写 I → 看 Q →stop。过程映像前 4 字节由 IO 控制器(主站)同步,从站不要周期把 Q 抄回 I。
from darra_pnet import PnetService
数据方向
| 区 | 方向 | 应用该做什么 |
|---|---|---|
| I(输入面) | 设备 → 控制器 | 写。write / svc[i] = / pdo.Out[i] / write_bool("I0.0", …) |
| Q(输出面) | 控制器 → 设备 | 读。read / svc[i] / pdo.In[i] / read_bool("Q0.0")。写 Q 失败 |
现场已通的是过程映像前 4 字节(主站同步)。写 I 后到 Q 上看主站回写,不要自造用户周期去抄区。
概览
| 类 | 职责 |
|---|---|
PnetService | 服务模式单一入口:connect() / start / stop / 写 I / 读 Q / 地址化 / pdo |
Pdo / PdoArray / PdoDataItem | ETH 式 PDO:In 只读 Q,Out 可写 I |
PnetServiceAddress / PnetServiceArea | HSL 式地址解析 |
PnetServiceStatus / PnetRuntimeErrorCode | 运行态快照 / 服务端错误码 |
PnetDevice 等 | native 直连备选,不是产品路径 |
PnetService.connect() — 无 host 主路径
from darra_pnet import PnetService, PnetServiceError
# 主路径:无 host,映射 GlobalIO,不探测 HTTP
with PnetService.connect() as svc:
svc.start() # 先映射;已映射不 POST /api/start
svc.write(b"\x01\x02\x03\x04") # 写 I(设备 → 控制器)
q = svc.read() # 读 Q(控制器 → 设备)
print(q[:4]) # 前 4 字节:主站同步
svc.stop() # 卸载映射;仅 header.Connected==0 才 POST /api/stop
# HTTP 备用(GUI / 本机诊断):构造即探测 GET /api/info
# with PnetService.connect("127.0.0.1") as svc:
# ...
生命周期:connect → start → 写 I / 读 Q / 地址化 / pdo → stop → close。无 Tick。
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
connect(host=None, port=18840, api_key=None) | PnetService | 设备 | 静态 | 无 host = 实时主路径(映射 GlobalIO,不探测 HTTP)。传 host = HTTP 备用(构造即 GET /api/info;服务仅监听 127.0.0.1:18840) |
start() | None | 设备 | 写 | 先映射 Section。已映射直接返回,不 POST /api/start。映射失败才走 HTTP 备用 |
stop() | None | 设备 | 写 | 先卸载映射。仅 header.Connected==0(未映射时仅服务端明确空闲)才 POST /api/stop。永远释放本实例 |
close() | None | 设备 | 写 | 释放会话,不向服务端发 stop。空会话 / 重复调用安全 |
is_connected | bool | 设备 | 只读 | 会话层是否仍有效(不是控制器 AR) |
is_started | bool | 设备 | 只读 | 本会话是否已 start |
host / port | str / int | 设备 | 只读 | HTTP 备用主机 / 固定端口 18840 |
DEFAULT_PORT | int | 设备 | 只读 | 18840(与服务端 PnetApiServer.FixedPort 同值,不可配置) |
写 I / 读 Q
svc.write(b"\x01\x02\x03\x04") # I:OutputArea + OutputDirty
q = svc.read() # Q:InputArea
print(svc[0]) # 从 PLC 读 Q[0]
svc[0] = 0xAA # 发给 PLC(写 I[0])
print(svc.input) # I 区快照(设备 → 控制器)
print(svc.output) # Q 区快照(控制器 → 设备)
已映射走共享内存;未映射才 GET/POST /api/io。允许短写。无用户周期。
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
write(data) | None | IO | 写 | 写 I(设备 → 控制器)。已映射写 OutputArea 并置 OutputDirty |
read() | bytes | IO | 只读 | 读 Q(控制器 → 设备)。已映射读 InputArea |
svc[offset] | int | IO | 只读 | 读 Q 一字节(从 PLC) |
svc[offset] = value | None | IO | 写 | 写 I 一字节(发给 PLC) |
input | bytes | IO | 只读 | I 区快照(设备 → 控制器) |
output | bytes | IO | 只读 | Q 区快照(控制器 → 设备) |
get_io() | (bytes, bytes) | IO | 只读 | 直打 GET /api/io,返回 (I, Q)。主 API 请用 read / write / input / output |
read_area(area, offset, length) | bytes | IO | 只读 | 整区批量读(I / Q / M) |
write_area(area, offset, data) | None | IO | 写 | 整区批量写(仅 I / M)。写 Q 抛 PnetServiceError |
地址化读写
HSL 式地址,与 C# PnetAddress.Parse 对齐。字 / 双字大端(PROFINET 网络序);偏移即字节偏移,不强制 2 / 4 对齐(IW3 合法)。服务模式是单一线性过程区,DB 仅槽位 1 有效。
svc.write_bool("I0.0", True) # 写 I 位
svc.write_int16("IW2", 0x1234) # 写 I 字(大端)
start = svc.read_bool("Q0.0") # 读 Q 位
cmd = svc.read_int16("QW2") # 读 Q 字
svc.write_bool("Q0.0", True) # 失败:Q 只读 → PnetServiceError
| 区域 | 地址格式 | 方向 | 写 |
|---|---|---|---|
| I 区 | I0.0 / IB0 / IW2 / ID4 | 设备 → 控制器 | 允许 |
| Q 区 | Q0.0 / QB0 / QW2 / QD4 | 控制器 → 设备 | 只读,写抛 PnetServiceError(NOT_AVAILABLE,文案含「Q 区 … 只读」) |
| M 区 | M0.0 / MB0 / MW100 / MD0 | 映射输入面 | 允许 |
| DB 区 | DB1.DBX0.0 / DB1.DBB2 / DB1.DBW0 / DB1.DBD4 | 槽位 1 数据块 | 写走 I 面;槽位 > 1 抛 PnetServiceError |
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
read_bool(address) | bool | IO | 只读 | 位:I0.0 / Q0.0 / M1.6 / DB1.DBX0.0 |
write_bool(address, value) | None | IO | 写 | 写位(I / M / DB)。写 Q 失败 |
read_int16(address) | int | IO | 只读 | 字:IW2 / QW2 / MW0 / DB1.DBW0,大端 |
write_int16(address, value) | None | IO | 写 | 写字(I / M / DB)。写 Q 失败 |
read_int32(address) | int | IO | 只读 | 双字:ID4 / QD4 / MD0 / DB1.DBD4,大端 |
write_int32(address, value) | None | IO | 写 | 写双字(I / M / DB)。写 Q 失败 |
parse_address(text) | PnetServiceAddress | IO | 静态 | 解析 HSL 式地址 |
PDO:In 读 Q / Out 写 I
对齐 ETH PDOArrayInstance / PdoDataItem。In 是合法标识符(主属性名);inn 是同一数组别名。偏移是过程映像字节地址。无用户周期,无 HTTP。
pdo = svc.pdo
print(pdo.In[0].content) # 读 Q[0](控制器 → 设备),只读
pdo.Out[0].content = 0x11 # 写 I[0](设备 → 控制器)
pdo.Out[2].as_int16 = -2 # 大端 Int16
status, pos = pdo.read_struct("Hi")
pdo.write_struct("Hi", 1, -2)
pdo.In[0].content = 1 # 失败:RuntimeError(In 只读,写请用 Out)
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
pdo | Pdo | PDO | 只读 | 懒创建。In = Q 只读,Out = I 可写 |
pdo.In / pdo.inn | PdoArray | PDO | 只读 | In[i].content 读 Q。写 In 抛 RuntimeError |
pdo.Out | PdoArray | PDO | 读写 | Out[i].content = v 写 I;Out[i] = v 等价 |
PdoArray.length | int | PDO | 只读 | 当前过程映像字节长度 |
PdoDataItem.content | int | PDO | 读写 | 1 字节。In 读 Q;Out 写 / 回读 I |
as_int16 / as_uint16 | int | PDO | 读写 | 大端 16 位(写仅 Out) |
as_int32 / as_uint32 | int | PDO | 读写 | 大端 32 位(写仅 Out) |
as_float | float | PDO | 读写 | 大端 float(写仅 Out) |
get_bit(bit) / set_bit(bit, value) | bool / None | PDO | 读写 | 本字节位 0–7。set_bit 仅 Out |
read_struct(fmt) | tuple | PDO | 只读 | 从 Q struct.unpack('>'+fmt) |
write_struct(fmt, *values) | None | PDO | 写 | 大端 pack 后整段写 I |
inputs_mapping(fmt=None) | bytes / tuple | PDO | 只读 | Q 区快照;有 fmt 则 unpack |
copy_inputs_to(buf) | int | PDO | 只读 | 把当前 Q 拷到调用方缓冲 |
copy_to_outputs(src) | int | PDO | 写 | 把调用方缓冲写入 I(允许短写) |
运行态
已映射时 state / connected 只信共享内存头(header.Connected / 驱动 State),不假绿。error_code 主返回枚举,不要把裸 int 当主 API。
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
state | PnetState | 设备 | 只读 | 已映射走驱动 State;否则 GET /api/status。未启动 = NONE |
connected | bool | 设备 | 只读 | 是否已与 IO 控制器建立周期数据交换。已映射只信 header.Connected |
error_code | PnetRuntimeErrorCode | 设备 | 只读 | 枚举主返回。未识别 = UNKNOWN |
error_code_enum | PnetRuntimeErrorCode | 设备 | 只读 | 旧名,转调 error_code |
status() | str | 设备 | 只读 | 服务端状态原文字符串(旧接口,诊断用) |
status_ex() | PnetServiceStatus | 设备 | 只读 | GET /api/status 一次取回 state / connected / error_code(裸 int 仅此快照字段) |
PnetState:NONE / IDLE / CONNECTING / PARAMETERIZED / APPLICATION_READY / DATA_EXCHANGE / ABORTED / RESETTING / CONFIG_ERROR / UNKNOWN。
PnetRuntimeErrorCode:OK=0 / ERR_INIT=-1 / ERR_CFG=-2 / ERR_THREAD=-3 / ERR_RUNNING=-4 / ERR_PDI=-5 / ERR_DAP=-6 / ERR_NULL=-8 / ERR_DIAG=-9 / UNKNOWN=-10000。
旧 get_state / get_error_code / get_connected / get_input / get_output 一律转调上表属性,不是主 API。
HTTP 备用
PnetService.connect("127.0.0.1")(或 PnetService("127.0.0.1", 18840))构造即探测 GET /api/info。服务未开放局域网监听;非回环地址连不上。实时 IO 仍应走无 host 主路径。
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
get_alarms() | list[PnetServiceAlarm] | 报警 | 只读 | GET /api/alarms |
ack_alarm(id) / ack_all_alarms() | None / int | 报警 | 写 | POST /api/alarms/ack / ack-all |
send_process_alarm(slot, subslot, usi, payload=None) | None | 报警 | 写 | POST /api/alarm |
get_im_data() | PnetServiceImData | 标识 | 只读 | GET /api/im |
get_records() | PnetServiceRecords | 记录 | 只读 | GET /api/records |
reset_device(mode) | None | 设备 | 写 | POST /api/reset(communication / factory) |
薄 SDK 无配置下发。网卡 / 站名由 GUI → 运行配置 XML → Service 加载。设备对外只开放一个 PROFINET 网口。
完整示例
from darra_pnet import PnetService, PnetServiceError
with PnetService.connect() as svc: # 无 host = SHM 主路径
svc.start()
# 无用户周期:写 I,看 Q。前 4 字节由主站同步
svc.write(b"\x01\x02\x03\x04")
q = svc.read()
print("Q 前 4 字节:", q[:4])
svc.write_bool("I0.0", True)
print("Q0.0 =", svc.read_bool("Q0.0"))
svc.pdo.Out[1].content = 0x22
print("In[1] =", svc.pdo.In[1].content)
try:
svc.write_bool("Q0.0", True)
except PnetServiceError as e:
print("Q 只读:", e)
svc.stop()
安装
pip install darra-pnet
或本地源码:
cd Darra_Pnet_SDK/Python
pip install -e .
运行前提:Darra PnSlave 服务已启动,且驱动已创建 \\Device\\DarraRT_Pnet_GlobalIO(Windows,通常需管理员)。HTTP 备用可在本机访问 127.0.0.1:18840。
native 直连(备选,非产品路径)
PnetDevice / PnetSlave / PnetIo 仍导出,供形态对照。产品与测试主路径是上面的 PnetService.connect()。不要在应用里自建周期循环,也不要把 native 当默认入口。