Python API 参考
Python SDK(包 darra_pnet,ctypes 直连原生 DarraPnet.dll,简化实现不做 Cython)。含两种形态:服务模式(推荐) — PnetService 单一入口,经 Pnet Service 内置 HTTP API(端口 18840 固定)连接,由服务承载从站运行(标准库 http.client,会话内连接复用,不依赖 native DLL);native 直连(备选) — 应用内加载 DarraPnet.dll,创建 PnetDevice → 配置 → 启停 → 槽位 IO 读写。命名采用 Python 惯例(snake_case),语义与 C# 页一致。
单一 PROFINET 网口契约(audit-2026-08-11,用户裁定 2026-08-10):设备对外只开放一个 PROFINET 网口(工业现场常态)。网卡选择在 GUI / Service 配置层完成,服务侧单一权威 =
NetworkInterfaceName(读取链:环境变量DARRA_PNET_NIC> 运行配置 XML<Network/InterfaceName>> appsettings 出厂默认;驱动绑定 / pnal 绑定目标 / MAC 解析同源一致,无双配置歧义)。native 直连模式下配置的网卡名为栈绑定的唯一网口名;EnumerateInterfaces()仅作诊断/枚举用途。
import darra_pnet as pnet
概览
| 类 | 职责 |
|---|---|
PnetDevice | 设备创建 / 配置 / 启停(加载 DarraPnet.dll) |
PnetSlave | 从站控制(站名 / IP / 输入输出区) |
PnetIo | 槽位过程数据读写 |
PnetAlarm | 报警发送 / 应答 |
PnetConfigService | 运行配置 XML 加载 / 导出(只读) |
PnetDiag | 诊断 / 统计 |
PnetService — 服务模式(推荐,已实现)
经服务 HTTP API(端口 18840 固定)连接服务,由服务承载从站运行;SDK 与 Web API 同层。启停(POST /api/start|stop)/ IO(GET|POST /api/io)全部经服务转发,不直连 native。连接复用:标准库 http.client 会话内复用单个 HTTP/1.1 keep-alive 连接(对齐 C# 共享 HttpClient)。
from darra_pnet import PnetService
with PnetService("127.0.0.1", 18840, None) as svc: # 端口固定 18840
svc.start() # POST /api/start
svc.write_bool("I0.0", True) # 写输入位(设备 → 控制器)
svc.write_int16("IW2", 0x1234) # 写输入字(大端)
start = svc.read_bool("Q0.0") # 读输出位(控制器 → 设备)
cmd = svc.read_int16("QW2") # 读输出字(大端)
i_area, q_area = svc.get_io() # 服务端过程映像快照(I 区 / Q 区)
svc.stop() # POST /api/stop(幂等)
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
PnetService(host, port, api_key) | PnetService | 设备 | 构造 | 连接服务(仅本地回环 127.0.0.1 可达,audit-2026-08-10:服务未开放局域网监听;端口固定 18840;服务端配置 API 密钥后必传) |
start() | None | 设备 | 写 | 启动从站(POST /api/start,由服务承载;失败如实抛 PnetServiceError) |
stop() | None | 设备 | 写 | 停止从站(POST /api/stop,幂等) |
status() | str | 设备 | 只读 | 服务端运行态(GET /api/status,状态字符串) |
status_ex() | PnetServiceStatus | 设备 | 只读 | 服务端运行态快照(GET /api/status 一次取回 state / connected / errorCode;用户裁定 2026-08-10:错误码是调用契约的一部分,SDK 必须透出服务端 connected / errorCode) |
connected | bool | 设备 | 只读 | 是否已与 IO 控制器建立周期数据交换(服务模式,GET /api/status 的 connected 原值) |
error_code | int | 设备 | 只读 | 最近一次错误码原值(服务模式,GET /api/status 的 errorCode 原值透传;0 = 无错误,非零 = pnet 栈错误码,语义见 PnetRuntimeErrorCode) |
error_code_enum | PnetRuntimeErrorCode | 设备 | 只读 | 最近一次错误码的枚举化映射(未识别值如实返回 UNKNOWN,原始值仍经 error_code 透传) |
is_connected / is_started | bool | 设备 | 只读 | 会话 / 本地启动状态 |
read_bool(address) / write_bool(address, value) | bool / None | IO | 读写 | 位地址(I0.0 / Q0.0 / M1.6 / DB1.DBX0.0;Q 区只读,写抛异常) |
read_int16(address) / write_int16(address, value) | int / None | IO | 读写 | 字地址(IW2 / QW2 / MW0 / DB1.DBW0,大端) |
read_int32(address) / write_int32(address, value) | int / None | IO | 读写 | 双字地址(ID4 / QD4 / MD0 / DB1.DBD0,大端) |
get_io() | (bytes, bytes) | IO | 只读 | 服务端过程映像快照(I 区 / Q 区) |
parse_address(text) | PnetServiceAddress | IO | 静态 | 解析 HSL 式地址(对齐 C# PnetAddress.Parse) |
地址格式(与 C# 基准一致):I0.0 / IB0 / IW2 / ID4(I 区输入面)、Q0.0 / QB0 / QW2 / QD4(Q 区输出面,只读)、M0.0 / MB0 / MW100 / MD0(内部存储)、DB1.DBX0.0 / DB1.DBB2 / DB1.DBW0 / DB1.DBD4(DB 区槽位 1 数据块)。字 / 双字大端序,偏移即字节偏移、不强制 2 / 4 对齐(IW3 合法);连接服务模式为单一线性过程区,DB 仅槽位 1 有效(槽位 > 1 抛 PnetServiceError)。
status_ex() 返回 PnetServiceStatus(state / connected / error_code / error_code_enum):connected = 是否已与 IO 控制器建立周期数据交换(GET /api/status 的 connected 原值),error_code = 最近一次错误码原值(0 = 无错误;非零 = pnet 栈错误码),error_code_enum = 枚举化映射(PnetRuntimeErrorCode:OK=0 / ERR_INIT=-1 / ERR_CFG=-2 / ERR_THREAD=-3 / ERR_RUNNING=-4 / ERR_PDI=-5 / UNKNOWN=-10000;未识别值如实返回 UNKNOWN,原始值仍经 error_code 透传)。connected / error_code / error_code_enum 亦可作为属性直接访问(每次访问即一次 GET /api/status)。
PnetDevice — 设备(native 直连,备选)
dev = pnet.PnetDevice() # 加载 DarraPnet.dll(按搜索路径)
dev.configure(cfg) # 应用运行配置
dev.start() # 启动 PROFINET 从站(等待控制器建 AR)
dev.stop()
dev.shutdown()
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
PnetDevice(dll_path=None) | PnetDevice | 设备 | 构造 | 创建设备实例(加载 DarraPnet.dll,支持上下文管理器) |
configure(config) | None | 设备 | 写 | 应用运行配置(PnetConfig.create 构造) |
start() | None | 设备 | 写 | 启动从站(DCP HELLO,等待控制器建 AR) |
stop() | None | 设备 | 写 | 停止从站 |
shutdown() | None | 设备 | 写 | 释放设备(先停止再 Pnet_Exit,幂等) |
initialize() | None | 设备 | 写 | 初始化设备(Pnet_Init 获取句柄,幂等) |
slave(index=0) | PnetSlave | 设备 | 只读 | 从站控制对象 |
enum_devices(dll_path=None) | list[PnetDeviceInfo] | 设备 | 静态 | 枚举系统内可用的 PROFINET 设备 |
version | PnetVersionInfo | 设备 | 只读 | DLL 版本信息 |
sdk_version | str | 设备 | 只读 | SDK 版本文本 |
is_initialized / is_started | bool | 设备 | 只读 | 初始化 / 启动状态 |
PnetSlave — 从站
slave = dev.slave(0)
slave.set_name("darra-pnet-01")
slave.set_input(b"\x01\x02\x03\x04") # 写整个输入区(设备 → 控制器)
out = slave.output # 读整个输出区(控制器 → 设备)
state = slave.connection_state
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
connection_state | PnetConnState | 从站 | 只读 | 连接状态枚举 |
is_connected | bool | 从站 | 只读 | 是否已连接(AR 已建立) |
name | str | 从站 | 只读 | 站点名 |
mac | str | 从站 | 只读 | MAC 地址 |
set_name(name) | None | 从站 | 写 | 设置站点名 |
set_ip(ip, mask, gateway) | None | 从站 | 写 | 设置静态 IP 配置 |
set_input(data) | None | 从站 | 写 | 写整个输入区(设备 → 控制器) |
input | bytes | 从站 | 读写 | 整个输入区数据 |
output | bytes | 从站 | 只读 | 整个输出区数据(控制器 → 设备) |
signal_led(state) | None | 从站 | 写 | LED 状态(红 / 绿) |
io | PnetIo | 从站 | 只读 | 槽位过程数据对象 |
alarm | PnetAlarm | 从站 | 只读 | 报警对象 |
config | PnetConfigService | 从站 | 只读 | 配置服务对象 |
diag | PnetDiag | 从站 | 只读 | 诊断对象 |
PnetIo — 槽位过程数据
io = slave.io
io.write(1, 1, bytes([0xAA, 0x01])) # 写槽位输入(设备 → 控制器)
data, iocs = io.read(1, 1) # 读槽位输出(控制器 → 设备)+ IOCS
whole = io.input # 整个输入区(与 slave.input 一致)
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
write(slot, subslot, data, iops=GOOD) | None | IO | 写 | 写槽位输入数据(设备 → 控制器) |
read(slot, subslot) | (bytes, PnetIoxs) | IO | 只读 | 读槽位输出数据 + IOCS 状态 |
read_data(slot, subslot) | bytes | IO | 只读 | 读槽位输出数据(仅数据) |
iocs | PnetIoxs | IO | 只读 | 最近一次读取的 IOCS |
input | bytes | IO | 读写 | 整个输入区数据 |
output | bytes | IO | 只读 | 整个输出区数据 |
PnetAlarm — 报警
slave.alarm.send(pnet.PnetAlarmType.PROCESS, 1, 1, b"\x01")
slave.alarm.ack(0, pnet.PnetAlarmType.PROCESS)
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
send(alarm_type, slot, subslot, payload) | None | 报警 | 写 | 发送报警 |
ack(api_id, alarm_type) | None | 报警 | 写 | 应答报警 |
active | list[PnetAlarmInfo] | 报警 | 只读 | 活动报警列表 |
active_count | int | 报警 | 只读 | 活动报警数 |
is_active | bool | 报警 | 只读 | 是否有活动报警 |
PnetConfigService — 配置
slave.config.load_xml("device.xml") # 加载运行配置 XML(GUI 输出)
n = slave.config.slot_count
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
load_xml(path) | None | 配置 | 写 | 从运行配置 XML 加载 |
export_xml(path) | None | 配置 | 写 | 导出运行配置 XML |
slot_count | int | 配置 | 只读 | 槽位数 |
slots | list[PnetSlotInfo] | 配置 | 只读 | 槽位列表 |
get_slot(index) | PnetSlotInfo | 配置 | 只读 | 读取槽位配置 |
device_id / vendor_id / product_id | int | 配置 | 只读 | 设备 / 厂商 / 产品标识 |
PnetDiag — 诊断
slave.diag.refresh()
print(slave.diag.frame_rx, slave.diag.frame_tx)
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
refresh() | None | 诊断 | 写 | 刷新统计快照 |
frame_rx / frame_tx / frame_error | int | 诊断 | 只读 | 收帧 / 发帧 / 帧错误计数 |
alarm_rx / alarm_tx / alarm_error | int | 诊断 | 只读 | 报警收 / 发 / 错误计数 |
ar_connect / ar_release | int | 诊断 | 只读 | AR 连接 / 释放计数 |
lost_cycles | int | 诊断 | 只读 | 丢失周期计数 |
last_error_code | int | 诊断 | 只读 | 最近错误码 |
has_error | bool | 诊断 | 只读 | 是否有错误 |
reset_counters() | None | 诊断 | 写 | 复位计数 |
counters | PnetDiagCounters | 诊断 | 只读 | 统计快照结构 |
summary | str | 诊断 | 只读 | 汇总文本 |
完整示例
import time
import darra_pnet as pnet
with pnet.PnetDevice() as dev:
cfg = pnet.PnetConfig.create(
station_name="darra-pnet-01",
ip=0xC0A80164, # 192.168.1.100(主机序 uint32)
period_us=1000,
)
dev.configure(cfg)
dev.start()
slave = dev.slave(0)
# 周期写整个输入区(保持 IOPS=Good)
input_data = bytearray([0x00, 0x00, 0xAA])
for _ in range(100):
input_data[2] = (input_data[2] + 1) & 0xFF
slave.set_input(bytes(input_data))
output = slave.output
time.sleep(0.01)
安装
pip install darra-pnet
或本地源码安装:
cd Darra_Pnet_SDK/Python
pip install -e .