Passive Server
基于 SECS/GEM (HSMS) 协议的半导体设备通信中间件,实现工厂 EAP/MES 与设备 PLC 之间的数据交互。支持 Equipment(设备端)和 Host(主机端)两种运行模式。
架构概览
Equipment 模式(设备端)
设备端模式直接连接 PLC,监控设备状态并通过 SECS/HSMS 协议与工厂 EAP 通信。
graph TD
EAP["工厂 EAP (Active)"]
PS["PassiveServer\n(SECS/HSMS Passive)"]
PLC["设备 PLC"]
WEB["Web 前端页面"]
DB["MySQL 数据库"]
SOCKET["Socket\n下位机客户端"]
EAP -->|"SECS/HSMS\nS1~S10 流函数"| PS
PS -->|"S5F1 报警\nS6F11 事件"| EAP
PS -->|"Snap7 / Modbus\nMELSEC / Tag"| PLC
PS -->|"HTTP POST\n实时推送"| WEB
PS -->|"SQLAlchemy\n读写配置"| DB
PS -->|"异步 Socket\n数据交互"| SOCKET
Host 模式(主机端)
Host 模式作为中间代理,连接工厂 EAP 和多台设备,负责指令转发和状态汇总。
graph TD
EAP["工厂 EAP (Active)"]
HP["HostPassive\n(SECS/HSMS Passive)"]
AH["ActiveHost\n(HSMS Active)"]
EQ1["设备 #1\n(Passive Service)"]
EQ2["设备 #2\n(Passive Service)"]
EQ3["设备 #N\n(Passive Service)"]
DB["MySQL 数据库"]
WEB["Web 前端页面"]
EAP -->|"SECS/HSMS 流函数"| HP
HP -->|"事件/报警转发"| EAP
HP -->|"指令转发\n状态汇总"| AH
AH -->|"HSMS Active"| EQ1
AH -->|"HSMS Active"| EQ2
AH -->|"HSMS Active"| EQ3
EQ1 -->|"事件/报警上报"| AH
EQ2 -->|"事件/报警上报"| AH
EQ3 -->|"事件/报警上报"| AH
HP -->|"HTTP POST"| WEB
HP -->|"SQLAlchemy"| DB
信号监控流程
设备端模式下,系统启动多个后台线程持续监控 PLC 信号变化并触发对应操作。
graph TD
START["服务启动"] --> HEART["MES 心跳线程\n定时翻转心跳位"]
START --> CTRL["控制状态监控\n本地/远程模式切换"]
START --> PROC["运行状态监控\n运行/报警状态变化"]
START --> RECIPE["配方监控\n当前配方变更检测"]
START --> SIGNAL["自定义信号监控\nsignal_address_list"]
SIGNAL --> S1["Step 1: 读 PLC 地址"]
S1 --> S2["Step 2: 写 PLC 地址"]
S2 --> S3["Step 3: 执行自定义函数"]
S3 --> S4["Step 4: 等待工厂回复"]
S4 --> S5["Step 5: 发送事件 S6F11"]
S5 --> S6["Step 6: 清除信号位"]
CTRL --> EVENT1["发送 ControlStateChange 事件"]
PROC --> EVENT2["发送 ProcessStateChange 事件"]
PROC --> ALARM["触发报警 S5F1"]
功能特性
- 完整的 SECS/GEM 协议支持:处理 S1F15/S1F17(在线/离线)、S2F17/S2F31(时间同步)、S2F33/S2F35/S2F37(报告/事件定义)、S5F1/S5F3/S5F5(报警管理)、S6F11(事件上报)、S7F1~S7F26(配方管理)、S10F3(终端显示)等标准流函数
- 多 PLC 协议支持:西门子 S7 (Snap7)、三菱 (MELSEC)、Modbus TCP、汇川标签通讯 (Inovance Tag)
- 数据库驱动配置:SV/EC/DV、事件、报警、报告、远程命令、PLC 地址映射等全部通过 MySQL 管理,无需修改代码
- 实时 PLC 信号监控:监控 PLC 地址信号变化,触发自定义多步骤流程(读/写/函数调用/事件上报/等待工厂回复)
- Socket 通信:内置异步 Socket 服务端,支持与下位机或其他系统通信
- Web 前端联动:数据变更自动通知前端页面刷新,支持实时状态展示
- 日志管理:按天自动轮转日志,统一管理 SECS 通信日志和业务日志
- 远程配方管理:支持工厂通过 S7Fx 系列流函数下发/删除/查询配方
环境要求
| 依赖 | 版本 |
|---|---|
| Python | >= 3.11, < 3.13 |
| MySQL | 5.7+ / 8.0+ / 9.0+ |
| 操作系统 | Windows |
快速开始
安装依赖
本项目使用 Poetry 管理依赖:
git clone https://gitee.com/w_liu/passive_server.git
cd passive_server
poetry install
编写启动类
Equipment 模式:
import asyncio
import json
from typing import Optional
from passive_server.passive_equipment import EquipmentPassive
class EquipmentExample(EquipmentPassive):
def __init__(self, mysql_host: str, database_name: str):
super().__init__(mysql_host, database_name)
def _on_rcmd_new_lot(self, lot_name: str, lot_quantity: int):
"""开工单.
Args:
lot_name: 工单号.
lot_quantity: 工单数量.
"""
data = {"new_lot": {"lot_name": lot_name, "lot_quantity": lot_quantity}}
asyncio.run(self.send_data_to_socket_client(self.socket_server_low, "127.0.0.1", json.dumps(data)))
def _on_rcmd_pp_select(self, recipe_name: str) -> bool:
"""切换配方.
Args:
recipe_name: 配方名称.
Returns:
Optional[bool]: True 切换成功, False 切换失败
"""
self.logger.info("要切换的配方是 %s", recipe_name)
if self.get_sv_value_with_name("pp_select_state") == 1:
return True
return False
def _on_car_CarrierPurgeStart(self, carrier_action_dict: dict) -> tuple[int, list]:
"""收到 s3f17 下发的 carrier action 信息.
Args:
carrier_action_dict: carrier action 信息.
Returns:
tuple[int, list]: 返回 ca ack 和 错误信息列表, 不返回代表没有错误, ca_ack: 0: 没有错误, ca_ack: 不等于 0 有错误.
"""
self.logger.info("执行 _on_car_CarrierPurgeStart")
# todo 操作 plc
return 0, []
if __name__ == '__main__':
EquipmentExample("127.0.0.1", "big_beauty")
Host 模式:
from passive_server.passive_host import HostPassive
class HostExample(HostPassive):
def __init__(self):
super().__init__()
if __name__ == '__main__':
HostExample()
运行
运行Equipment 模式:
poetry run python equipment_example.py
运行Host 模式:
poetry run python host_example.py
核心数据库表
| 表名 | 说明 |
|---|---|
sv_list |
Status Variable 状态变量定义 |
dv_list |
Data Value 数据值定义 |
ec_list |
Equipment Constant 设备常量定义 |
event_list |
事件定义 |
report_list |
自定义报告定义 |
alarm_list |
报警定义(支持中英文) |
alarm_enabled |
工厂已启用的报警 |
alarm_record_list |
报警历史记录 |
address_list |
PLC 地址定义 |
plc_address_list |
PLC→MES 地址映射(含流程步骤) |
mes_address_list |
MES→PLC 地址映射(含流程步骤) |
signal_address_list |
PLC 信号地址定义 |
flow_func |
自定义流程函数配置 |
recipe_info |
配方数据存储 |
define_report |
工厂定义的报告 |
report_link_event |
工厂定义的事件-报告关联 |
lot_list |
工单列表 |
equipment_state |
设备状态记录 |
SECS 流函数支持
| 流函数 | 方向 | 说明 |
|---|---|---|
| S1F15 → S1F16 | 工厂→设备 | 请求离线 |
| S1F17 → S1F18 | 工厂→设备 | 请求在线 |
| S2F17 → S2F18 | 工厂→设备 | 获取设备时间 |
| S2F31 → S2F32 | 工厂→设备 | 设置设备时间 |
| S2F33 → S2F34 | 工厂→设备 | 定义报告 |
| S2F35 → S2F36 | 工厂→设备 | 链接事件和报告 |
| S2F37 → S2F38 | 工厂→设备 | 启用/停用事件 |
| S2F41 → S2F42 | 工厂→设备 | Host 命令(Host模式转发) |
| S2F49 → S2F50 | 工厂→设备 | 增强远程命令 |
| S3F17 → S3F18 | 工厂→设备 | Carrier 操作 |
| S5F1 → S5F2 | 设备→工厂 | 报警上报 |
| S5F3 → S5F4 | 工厂→设备 | 启用/停用报警 |
| S5F5 → S5F6 | 工厂→设备 | 查询报警列表 |
| S6F11 → S6F12 | 设备→工厂 | 事件上报 |
| S7F1 → S7F2 | 工厂→设备 | 配方下发许可询问 |
| S7F3 → S7F4 | 工厂→设备 | 配方下发 |
| S7F5 → S7F6 | 工厂→设备 | 请求上传配方 |
| S7F17 → S7F18 | 工厂→设备 | 删除配方 |
| S7F19 → S7F20 | 工厂→设备 | 查询所有配方名称 |
| S7F23 → S7F24 | 工厂→设备 | 格式化配方下发 |
| S7F25 → S7F26 | 工厂→设备 | 格式化配方上传 |
| S10F3 → S10F4 | 工厂→设备 | 终端显示 |
PLC 协议支持
| 协议 | PLC 类型 | 依赖库 | ec_name 标识 |
|---|---|---|---|
| S7 (Snap7) | 西门子 S7-300/400/1200/1500 | python-snap7 |
snap7 |
| MELSEC | 三菱 FX/Q/L 系列 | mitsubishi-plc |
mitsubishi |
| Modbus TCP | 通用 Modbus 设备 | modbus-api |
modbus |
| 标签通讯 | 汇川 (Inovance) | inovance-tag-plc |
tag |
核心依赖
secsgempro— SECS/GEM 协议实现sqlalchemy+pymysql— 数据库 ORMpython-snap7— 西门子 S7 PLC 通信siemens-plc— 西门子 PLC 封装mitsubishi-plc— 三菱 PLC 封装inovance-tag-plc— 汇川标签通讯modbus-api— Modbus 协议封装socket-pro— 异步 Socket 服务端mysql-api— MySQL 数据库操作封装
日志
日志文件存储在 log/ 目录下,按天轮转:
all.log— 当日日志all_YYYY-MM-DD.log— 历史日志
日志保留天数可通过 ec_list 表中的 log_save_day 配置。
License
内部项目,保留所有权利。
作者
WeiLiu 183074632@qq.com
Metadata
Release files for passive_server 1.46.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| passive_server-1.46.0.tar.gz | 35.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| passive_server-1.46.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.0 kB
Release files / passive_server-1.46.0.tar.gz
| Download URL | passive_server-1.46.0.tar.gz |
|---|---|
| Size | 35.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1cb74d36d73120bd990144c845f815cb67fbea4fbc70f60436bdbe09420991ca
|
|
BLAKE2b-256 checksum How to use checksums |
4db7237765c538ba88978a6a513e594115011c32b74c5bb27ff4c5bc41a676f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.11.9 Windows/10
|
Release files / passive_server-1.46.0-py3-none-any.whl
| Download URL | passive_server-1.46.0-py3-none-any.whl |
|---|---|
| Size | 42.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6c051db87eeb550e2166ef857cccd67d2fa2da56e28125878a0ec9673be489dc
|
|
BLAKE2b-256 checksum How to use checksums |
567a63c309a833be449b40f16299b0d19c899afa008185d299fa66ac188b185f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.11.9 Windows/10
|