# S7 PLC数据采集功能说明 ## 概述 本功能实现了通过S7协议读取西门子PLC200 Smart设备的数据,支持定时自动采集和手动读写操作。 ## 功能特性 ### 1. 支持的地址类型 - **M区**: M0.1, M0.2 (位地址), M10 (字节地址) - **I区**: I0.1, I0.2 (输入位), I0 (输入字节) - **Q区**: Q0.1, Q0.2 (输出位), Q0 (输出字节) - **VB区**: VB12 (字节) - **VW区**: VW314 (字,2字节) - **VD区**: VD11 (双字,4字节,浮点数) - **AIW区**: AIW0, AIW64 (模拟量输入字,2字节,只读) - **AQW区**: AQW0, AQW64 (模拟量输出字,2字节,可读写) ### 2. 核心功能 - ✅ 定时自动采集(每5分钟执行一次) - ✅ 手动优先逻辑(Constant.WEB_FLAG为true时跳过采集) - ✅ 根据gateway_manage中community_type='S7'的dataCom查询采集参数 - ✅ 指令创建、下发、解析一体化 - ✅ 数据倍率、初始值、小数点处理 - ✅ 连接缓存管理,避免频繁创建连接 ## 文件结构 ``` user-service/src/main/java/com/mh/user/ ├── s7/ │ └── S7ConnectorUtil.java # S7通信工具类 ├── job/ │ └── S7PlcCollectionJob.java # 定时采集任务 ├── controller/ │ └── S7PlcController.java # 手动读写接口 └── mapper/ ├── GatewayManageMapper.java # 新增queryS7Gateways()方法 └── CollectionParamsManageMapper.java # 新增selectCPMByDataCom()方法 ``` ## 数据库配置 ### 1. gateway_manage表配置 ```sql -- 添加S7类型的网关记录 INSERT INTO gateway_manage ( gateway_name, gateway_ip, gateway_port, -- 格式: "rack,slot" 例如 "0,1" data_com, -- 通讯口标识,例如 "S7_PLC_1" community_type,-- 必须设置为 'S7' grade -- 连接状态: 1=在线 ) VALUES ( 'PLC200Smart_1', '192.168.1.100', '0,1', 'S7_PLC_1', 'S7', '1' ); ``` ### 2. device_install表配置 ```sql -- 添加设备安装记录,关联到S7网关 INSERT INTO device_install ( device_name, device_type, data_com, -- 与gateway_manage中的data_com一致 building_id ) VALUES ( 'S7设备1', 'PLC', 'S7_PLC_1', '1' ); ``` ### 3. collection_params_manage表配置 ```sql -- 添加采集点位配置 INSERT INTO collection_params_manage ( device_install_id, register_addr, -- 寄存器地址,如 M0.1, VB12, VW314, VD11 func_code, -- 功能码(可选) mt_ratio, -- 倍率 mt_init_value, -- 初始值 digits, -- 小数点位数 is_use, -- 是否启用: 1=启用 other_name, -- 点位别名(唯一) building_id ) VALUES ( 1, -- device_install_id 'M0.1', -- 寄存器地址 NULL, 1, -- 倍率 0, -- 初始值 2, -- 2位小数 1, -- 启用 'plc_status', -- 点位名称 '1' -- building_id ); ``` ## 使用方式 ### 1. 自动定时采集 系统启动后会自动执行定时任务,每5分钟采集一次所有S7网关的数据。 **定时任务配置:** - Cron表达式: `0 0/5 * * * ?` (每5分钟) - 可在`S7PlcCollectionJob.collectS7Data()`方法中修改 **手动优先逻辑:** - 当`Constant.WEB_FLAG = true`时,跳过本次采集 - 确保手动操作不被定时任务干扰 ### 2. 手动写入数据 **API接口:** ``` POST /s7plc/write 参数: - cpmId: 采集参数ID (Long) - value: 要写入的值 (Object) 返回: { "code": 200, "msg": "写入成功" } ``` **示例:** ```bash curl -X POST "http://localhost:8080/s7plc/write?cpmId=1&value=1" ``` ### 3. 清理连接缓存 **API接口:** ``` POST /s7plc/clearCache 返回: { "code": 200, "msg": "缓存清理成功" } ``` ## 代码示例 ### 在Service中调用手动写入 ```java @Autowired private S7PlcCollectionJob s7PlcCollectionJob; public void controlDevice(Long cpmId, Object value) { // 设置手动操作标志 Constant.WEB_FLAG = true; try { boolean success = s7PlcCollectionJob.writeData(cpmId, value); if (success) { log.info("控制成功"); } else { log.error("控制失败"); } } finally { Constant.WEB_FLAG = false; } } ``` ## 注意事项 ### 1. PLC连接配置 - **IP地址**: 确保gateway_manage.gatewayIP正确配置 - **Rack/Slot**: 默认为0,1,可通过gatewayPort字段配置(格式: "rack,slot") - **网络**: 确保服务器能访问PLC的IP地址和端口(默认102) ### 2. 数据类型映射 | 地址类型 | 数据类型 | DaveArea | 说明 | |---------|---------|----------|------| | M0.1 | Boolean | FLAGS | 位地址,返回0或1 | | M10 | Byte | FLAGS | 字节地址,返回0-255 | | I0.1 | Boolean | INPUTS | 输入位,返回0或1(只读) | | I0 | Byte | INPUTS | 输入字节,返回0-255(只读) | | Q0.1 | Boolean | OUTPUTS | 输出位,返回0或1 | | Q0 | Byte | OUTPUTS | 输出字节,返回0-255 | | VB12 | Byte | DB | V区字节,返回0-255 | | VW314 | Word | DB | V区字,返回0-65535 | | VD11 | Float | DB | V区双字,返回浮点数 | | AIW0 | Word | INPUTS | 模拟量输入字,返回0-65535(只读) | | AQW0 | Word | OUTPUTS | 模拟量输出字,返回0-65535 | ### 3. 注意事项 #### 读写权限说明 - **只读区域**: I区(输入)、AIW(模拟量输入) - 这些区域通常由PLC硬件控制,不建议写入 - **可写区域**: M区、Q区(输出)、V区、AQW(模拟量输出) - 尝试写入只读区域时会记录警告日志,但仍会执行写入操作 ### 4. 性能优化 - 连接器采用缓存机制,避免频繁创建连接 - 批量采集时使用同一个连接器实例 - 可通过`clearCache()`方法清理缓存 ### 5. 异常处理 - 连接失败会记录日志并跳过该网关 - 单个点位采集失败不影响其他点位 - 所有异常都会记录详细日志 ## 依赖库 项目已添加s7connector依赖: ```xml com.github.s7connector s7connector 2.1 ``` ## 后续优化方向 1. **连接池管理**: 实现更完善的连接池,支持断线重连 2. **批量读写**: 支持一次性读取多个点位,提高效率 3. **数据校验**: 增加数据范围校验和异常值过滤 4. **监控告警**: 添加PLC连接状态监控和异常告警 5. **配置化**: 将定时任务周期等参数配置化 6. **测试用例**: 编写单元测试和集成测试 ## 常见问题 ### Q1: 连接失败怎么办? - 检查PLC IP地址是否正确 - 检查网络连接是否正常 - 检查PLC是否允许S7通信 - 查看日志中的详细错误信息 ### Q2: 读取数据不正确? - 检查registerAddr格式是否正确 - 确认数据类型是否匹配(M/VB/VW/VD) - 检查倍率和初始值配置 - 对比PLC中的实际值 ### Q3: 如何调试? - 查看日志文件:`logs/user-service/info/` - 启用DEBUG日志级别 - 使用PLC仿真软件进行测试 ## 联系方式 如有问题,请联系开发团队。 --- **最后更新**: 2026-06-23