news 2026/4/16 12:43:35

OpenPLC Runtime v4 架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenPLC Runtime v4 架构

OpenPLC Runtime v4 架构

概述

OpenPLC Runtime v4 是一个双进程系统,通过一个用于 OpenPLC Editor 通信的 REST API 服务器和一个实时 PLC 执行引擎来提供工业自动化能力。

系统组件

1. REST API 服务器进程 (Python/Flask)

REST API 服务器是一个基于 Flask 的 HTTPS 应用程序,提供以下功能:

  • 用于 PLC 控制和管理的REST API
  • 用于实时调试的WebSocket 接口
  • 程序编译编排
  • 用户认证和安全
  • 运行时进程管理

关键细节:

  • 端口:8443 (HTTPS)
  • 位置:webserver/app.py
  • TLS:自签名证书(自动生成)
  • 认证:基于 JWT

2. PLC 运行时核心 (C/C++)

PLC 运行时是一个实时执行引擎,具备以下功能:

  • 以确定性的时序执行已编译的 PLC 程序
  • 通过插件驱动程序管理 I/O 操作
  • 为变量检查提供调试接口
  • 通过看门狗监控系统健康状态
  • 维护生命周期状态(INIT, RUNNING, STOPPED, ERROR, EMPTY)

关键细节:

  • 可执行文件:build/plc_main
  • 位置:core/src/plc_app/
  • 调度:SCHED_FIFO(实时优先级)
  • 要求:root 权限或 CAP_SYS_NICE 能力

进程间通信

两个进程通过 Unix 域套接字进行通信:

PLC 运行时套接字

  • 路径:/run/runtime/plc_runtime.socket
  • 目的:命令与控制(启动、停止、状态查询)
  • 协议:基于文本的命令,附带同步响应
  • 实现:core/src/plc_app/unix_socket.c(服务器端),webserver/unixclient.py(客户端)

日志套接字

  • 路径:/run/runtime/log_runtime.socket
  • 目的:将日志从 PLC 运行时实时流式传输到 REST API 服务器
  • 实现:core/src/plc_app/utils/log.c

PLC 生命周期状态

PLC 运行时维护以下状态:

EMPTY → INIT → RUNNING ⟷ STOPPED → ERROR

状态描述

  • EMPTY: 未加载 PLC 程序
  • INIT: 程序已加载,正在初始化
  • RUNNING: 正在主动执行扫描周期
  • STOPPED: 程序已加载但未执行
  • ERROR: 可恢复的错误状态

状态管理器:core/src/plc_app/plc_state_manager.c

线程模型

REST API 服务器线程

  1. 主 Flask 线程:处理来自 OpenPLC Editor 的 HTTP/HTTPS 请求
  2. WebSocket 线程:管理来自 OpenPLC Editor 的调试连接
  3. 编译线程:异步运行构建过程
  4. 运行时管理器线程:监控 PLC 运行时进程

PLC 运行时线程

  1. 主线程:初始化和信号处理
  2. Unix 套接字线程:接收和处理命令
  3. PLC 周期线程:以实时优先级执行扫描周期
  4. 统计线程:记录性能指标
  5. 看门狗线程:监控心跳,并在挂起时终止进程
  6. 日志线程:管理日志套接字连接

实时执行

PLC 周期线程以 SCHED_FIFO 优先级运行,以确保确定性的时序:

  1. 读取输入:插件驱动程序从硬件读取
  2. 执行逻辑:运行已编译的 PLC 程序 (ext_config_run__())
  3. 写入输出:插件驱动程序写入硬件
  4. 休眠至下一周期:使用clock_nanosleep()实现精确时序

时序配置:

  • 扫描周期持续时间:由ext_common_ticktime__定义(通常为 50ms)
  • 跟踪的时序统计:最小/最大/平均扫描时间、周期时间、延迟、超时

插件系统

运行时支持动态加载的插件以实现硬件 I/O:

  • 插件类型:Python 和 C/C++
  • 配置plugins.conf文件
  • 虚拟环境:每个插件具有独立的 Python 依赖环境
  • 缓冲区保护:在扫描周期内通过互斥锁保护的 I/O 缓冲区

文档:参见docs/PLUGIN_VENV_GUIDE.mdcore/src/drivers/README.md

安全架构

TLS/HTTPS

  • 首次运行时生成自签名证书
  • 证书文件:webserver/certOPENPLC.pem,webserver/keyOPENPLC.pem
  • 主机名验证以防止注入攻击

认证

  • 用于 API 和 WebSocket 访问的 JWT 令牌
  • 密钥存储在/var/run/runtime/.env
  • 用于密码哈希的 256 位加密胡椒

文件上传安全

  • ZIP 文件验证(路径遍历、大小限制、压缩率)
  • 禁止的扩展名:.exe, .dll, .sh, .bat, .js, .vbs, .scr
  • 最大文件大小:单个文件 10 MB,总计 50 MB
  • 解压过程中剥离 macOS 元数据

实现:webserver/plcapp_management.py,webserver/credentials.py

数据持久化

运行时数据目录

位置:/var/run/runtime/

包含:

  • .env- 环境变量(JWT 密钥、数据库 URI、胡椒)
  • restapi.db- 用于用户账户的 SQLite 数据库
  • 套接字文件(运行时创建)

Docker 卷

在 Docker 中运行时,将/var/run/runtime挂载为命名卷以实现持久化:

dockerrun -v openplc-runtime-data:/var/run/runtime...

看门狗系统

看门狗通过跟踪plc_heartbeat原子变量来监控 PLC 健康状态:

  • 更新频率:每个扫描周期
  • 超时:2 秒内无更新
  • 动作:如果 PLC 无响应,则终止进程
  • 状态感知:仅在 RUNNING 状态下监控

实现:core/src/plc_app/utils/watchdog.c

性能监控

运行时跟踪详细的时序统计信息:

  • 扫描计数:执行的总周期数
  • 扫描时间:执行 PLC 逻辑花费的时间
  • 周期时间:每个周期的总时间(包括休眠)
  • 周期延迟:与目标时序的偏差
  • 超时:超过目标持续时间的周期

统计信息通过统计线程每 5 秒记录一次。

错误处理

REST API 服务器

  • 构建失败在BuildStatus枚举中跟踪
  • 编译日志流式传输到 OpenPLC Editor
  • 运行时断开连接时的优雅降级

PLC 运行时

  • 对 SIGINT 进行信号处理(优雅关闭)
  • 执行前验证状态转换
  • 插件故障与核心运行时隔离
  • 看门狗确保进程在挂起时终止

目录结构

openplc-runtime/ ├── webserver/ # Flask REST API 服务器 │ ├── app.py # 主应用程序入口 │ ├── restapi.py # REST API 蓝图 │ ├── debug_websocket.py # WebSocket 调试接口 │ ├── unixclient.py # Unix 套接字客户端 │ ├── plcapp_management.py # 构建编排 │ ├── runtimemanager.py # 运行时进程控制 │ ├── credentials.py # TLS 证书生成 │ └── config.py # 配置管理 ├── core/ │ ├── src/plc_app/ # PLC 运行时源代码 │ │ ├── plc_main.c # 主入口点 │ │ ├── plc_state_manager.c/h # 状态管理 │ │ ├── unix_socket.c/h # IPC 服务器 │ │ ├── debug_handler.c/h # 调试协议 │ │ └── utils/ # 实用工具(日志、看门狗、计时) │ ├── src/drivers/ # 插件驱动系统 │ └── generated/ # 生成的 PLC 代码(运行时) ├── scripts/ # 构建和管理脚本 │ ├── compile.sh # 编译 PLC 程序 │ ├── compile-clean.sh # 清理和重命名库 │ └── manage_plugin_venvs.sh # 插件虚拟环境管理 ├── build/ # 编译输出 │ ├── plc_main # 编译的运行时可执行文件 │ └── libplc_*.so # 编译的 PLC 程序库 └── venvs/ # Python 虚拟环境 ├── runtime/ # Web 服务器虚拟环境 └── {plugin_name}/ # 每个插件的虚拟环境

部署模式

原生 Linux

  • 通过install.sh直接安装
  • 通过包管理器安装系统依赖项
  • 使用start_openplc.sh启动运行时

Docker 容器

  • 官方镜像:ghcr.io/autonomy-logic/openplc-runtime:latest
  • 多架构支持:amd64, arm64, armv7
  • 需要为/var/run/runtime提供持久化卷
  • 暴露端口 8443 用于 HTTPS 访问

开发

  • 使用 CMake 进行本地构建
  • 包含测试环境的开发容器
  • 用于代码质量的预提交钩子

相关文档

  • 编辑器集成 - OpenPLC Editor 如何连接到运行时
  • 编译流程 - 构建流水线详情
  • API 参考 - REST 端点和响应
  • 调试协议 - WebSocket 调试接口
  • 插件系统 - 硬件 I/O 插件
  • 安全 - 认证和文件验证
  • Docker 部署 - 容器使用
  • 故障排除 - 常见问题
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 5:23:35

每天一个网络知识:什么是链路备份?

大家想象一个场景: 如果学校的教务系统、选课系统、实验平台突然连不上了,你觉得问题最可能出在哪? 很多同学第一反应是: “服务器崩了”或者“系统出 bug 了”。 但在真实环境中,一个非常常见的原因是&#xff1a…

作者头像 李华
网站建设 2026/4/12 9:07:56

Java助力剪辑接单报价比价系统源码开发

Java在剪辑接单报价比价系统源码开发中发挥着核心作用,以下从技术架构、核心功能、源码实现及优势等维度进行深度解析: 一、技术架构:高可用与可扩展性 分层架构 表现层:采用Vue3 Uni-app跨端方案,一套代码编译生成…

作者头像 李华
网站建设 2026/3/19 8:22:27

Claude Code提示词案例(页面滚动切换nav组件主题)

E:\source\website-admin\ui\src\components\nav组件,目前这个组件只有一个主题色,页面滚动时position: sticky;会让nav组件吸顶,需求如下: 1. 页面向下滚动超过nav的高度后改变nav为浅色主题,浅色主题如下&#xff1a…

作者头像 李华
网站建设 2026/4/8 12:59:36

格式总出错?AI论文写作软件 千笔写作工具 VS 笔捷Ai 专科生必备

随着人工智能技术的迅猛迭代与普及,AI辅助写作工具已逐步渗透到高校学术写作场景中,成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生,开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

作者头像 李华
网站建设 2026/4/16 11:59:00

告别论文焦虑:我用百考通AI高效搞定硕士毕业论文的实战分享

又到一年毕业季,无数硕士生对着空白的Word文档发愁。从选题构思到文献整理,从数据分析到格式调整,毕业论文似乎总是一座难以逾越的大山。很多同学熬到深夜,却依然对着屏幕无从下手;反复修改开题报告,却总是…

作者头像 李华