跳到主要内容

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)
connectedbool设备只读是否已与 IO 控制器建立周期数据交换(服务模式,GET /api/status 的 connected 原值)
error_codeint设备只读最近一次错误码原值(服务模式,GET /api/status 的 errorCode 原值透传;0 = 无错误,非零 = pnet 栈错误码,语义见 PnetRuntimeErrorCode
error_code_enumPnetRuntimeErrorCode设备只读最近一次错误码的枚举化映射(未识别值如实返回 UNKNOWN,原始值仍经 error_code 透传)
is_connected / is_startedbool设备只读会话 / 本地启动状态
read_bool(address) / write_bool(address, value)bool / NoneIO读写位地址(I0.0 / Q0.0 / M1.6 / DB1.DBX0.0;Q 区只读,写抛异常)
read_int16(address) / write_int16(address, value)int / NoneIO读写字地址(IW2 / QW2 / MW0 / DB1.DBW0,大端)
read_int32(address) / write_int32(address, value)int / NoneIO读写双字地址(ID4 / QD4 / MD0 / DB1.DBD0,大端)
get_io()(bytes, bytes)IO只读服务端过程映像快照(I 区 / Q 区)
parse_address(text)PnetServiceAddressIO静态解析 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() 返回 PnetServiceStatusstate / connected / error_code / error_code_enum):connected = 是否已与 IO 控制器建立周期数据交换(GET /api/status 的 connected 原值),error_code = 最近一次错误码原值(0 = 无错误;非零 = pnet 栈错误码),error_code_enum = 枚举化映射(PnetRuntimeErrorCodeOK=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 设备
versionPnetVersionInfo设备只读DLL 版本信息
sdk_versionstr设备只读SDK 版本文本
is_initialized / is_startedbool设备只读初始化 / 启动状态

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_statePnetConnState从站只读连接状态枚举
is_connectedbool从站只读是否已连接(AR 已建立)
namestr从站只读站点名
macstr从站只读MAC 地址
set_name(name)None从站设置站点名
set_ip(ip, mask, gateway)None从站设置静态 IP 配置
set_input(data)None从站写整个输入区(设备 → 控制器)
inputbytes从站读写整个输入区数据
outputbytes从站只读整个输出区数据(控制器 → 设备)
signal_led(state)None从站LED 状态(红 / 绿)
ioPnetIo从站只读槽位过程数据对象
alarmPnetAlarm从站只读报警对象
configPnetConfigService从站只读配置服务对象
diagPnetDiag从站只读诊断对象

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)NoneIO写槽位输入数据(设备 → 控制器)
read(slot, subslot)(bytes, PnetIoxs)IO只读读槽位输出数据 + IOCS 状态
read_data(slot, subslot)bytesIO只读读槽位输出数据(仅数据)
iocsPnetIoxsIO只读最近一次读取的 IOCS
inputbytesIO读写整个输入区数据
outputbytesIO只读整个输出区数据

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报警应答报警
activelist[PnetAlarmInfo]报警只读活动报警列表
active_countint报警只读活动报警数
is_activebool报警只读是否有活动报警

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_countint配置只读槽位数
slotslist[PnetSlotInfo]配置只读槽位列表
get_slot(index)PnetSlotInfo配置只读读取槽位配置
device_id / vendor_id / product_idint配置只读设备 / 厂商 / 产品标识

PnetDiag — 诊断

slave.diag.refresh()
print(slave.diag.frame_rx, slave.diag.frame_tx)
成员类型类别读写说明
refresh()None诊断刷新统计快照
frame_rx / frame_tx / frame_errorint诊断只读收帧 / 发帧 / 帧错误计数
alarm_rx / alarm_tx / alarm_errorint诊断只读报警收 / 发 / 错误计数
ar_connect / ar_releaseint诊断只读AR 连接 / 释放计数
lost_cyclesint诊断只读丢失周期计数
last_error_codeint诊断只读最近错误码
has_errorbool诊断只读是否有错误
reset_counters()None诊断复位计数
countersPnetDiagCounters诊断只读统计快照结构
summarystr诊断只读汇总文本

完整示例

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 .

相关