| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- package com.mes.util;
- import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
- import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.nio.charset.StandardCharsets;
- /**
- * 西门子 S7-200 SMART PLC 通信服务。
- * <p>
- * 使用 iot-communication 库的 S200_SMART 协议(支持 V 区原生地址,如 V2800.3、VB3000)。
- * s7connector 不支持 S7-200 SMART,请勿混用。
- */
- public class PlcService {
- public static final Logger log = LoggerFactory.getLogger(PlcService.class);
- private static S7PLC s7PLC;
- private static String plcIp = "192.168.2.1";
- private static int rack = 0;
- private static int slot = 0;
- private static volatile boolean connected = false;
- public static void setPlcIp(String ip) {
- if (ip != null && !ip.trim().isEmpty()) {
- plcIp = ip.trim();
- }
- }
- public static void setConnectionParams(int rackNo, int slotNo) {
- rack = rackNo;
- slot = slotNo;
- }
- public static String getPlcIp() {
- return plcIp;
- }
- public static boolean isConnected() {
- return connected;
- }
- public static synchronized boolean connect() {
- disconnect();
- try {
- s7PLC = new S7PLC(EPlcType.S200_SMART, plcIp, 102, rack, slot);
- s7PLC.setPersistence(true);
- s7PLC.setConnectTimeout(3000);
- s7PLC.setReceiveTimeout(3000);
- s7PLC.connect();
- s7PLC.readBoolean(addr(QmPlcPoint.STATUS_BYTE, QmPlcPoint.DATA_READY_BIT));
- connected = true;
- log.info("S7-200 SMART PLC连接成功: {} rack={} slot={}", plcIp, rack, slot);
- return true;
- } catch (Exception e) {
- connected = false;
- closeQuietly();
- log.info("S7-200 SMART PLC连接失败: {} - {}", plcIp, e.getMessage());
- return false;
- }
- }
- public static synchronized void disconnect() {
- connected = false;
- closeQuietly();
- s7PLC = null;
- }
- private static void closeQuietly() {
- if (s7PLC != null) {
- try {
- s7PLC.close();
- } catch (Exception ignored) {
- }
- }
- }
- public static synchronized boolean ensureConnected() {
- if (connected && s7PLC != null) {
- try {
- if (s7PLC.checkConnected()) {
- s7PLC.readBoolean(addr(QmPlcPoint.STATUS_BYTE, QmPlcPoint.DATA_READY_BIT));
- return true;
- }
- } catch (Exception e) {
- connected = false;
- }
- }
- return connect();
- }
- public static byte[] readStatusByte() {
- ensureConnectedOrThrow();
- return s7PLC.readByte("V" + QmPlcPoint.STATUS_BYTE, 1);
- }
- public static byte[] readMesDataBlock() {
- ensureConnectedOrThrow();
- return s7PLC.readByte("V" + QmPlcPoint.DATA_OFFSET, QmPlcPoint.DATA_LENGTH);
- }
- public static boolean isDataReady(byte[] statusByte) {
- return QmPlcPoint.readBool(statusByte, 0, QmPlcPoint.DATA_READY_BIT);
- }
- public static boolean readDataReady() {
- ensureConnectedOrThrow();
- return s7PLC.readBoolean(addr(QmPlcPoint.STATUS_BYTE, QmPlcPoint.DATA_READY_BIT));
- }
- public static boolean setCollectComplete(boolean complete) {
- return writeVBit(QmPlcPoint.STATUS_BYTE, QmPlcPoint.COLLECT_COMPLETE_BIT, complete);
- }
- /**
- * 上位机采集完成反馈:V2800.3 写1并保持1~3秒后复位为0。
- */
- public static boolean pulseCollectComplete() {
- if (!setCollectComplete(true)) {
- return false;
- }
- try {
- Thread.sleep(QmPlcPoint.COLLECT_COMPLETE_PULSE_MS);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- log.info("V2800.3脉冲被中断");
- return false;
- }
- return setCollectComplete(false);
- }
- public static boolean isQrMatchComplete(byte[] statusByte) {
- return QmPlcPoint.readBool(statusByte, 0, QmPlcPoint.QR_MATCH_BIT);
- }
- public static boolean setMesConnected(boolean connectedFlag) {
- return writeVBit(QmPlcPoint.STATUS_BYTE, QmPlcPoint.MES_CONNECTED_BIT, connectedFlag);
- }
- public static String readMesData() {
- byte[] data = readMesDataBlock();
- if (data == null) {
- log.warn("读取VB3000失败: 返回null");
- return "";
- }
- log.info("读取VB3000完成, byteLength={}", data.length);
- return QmPlcPoint.readPlcString(data);
- }
- /**
- * 质量校验通过后,将扫码内容写入 VB3500(纯 ASCII 原始字符串,无长度字节前缀)。
- */
- public static boolean writeScanCode(String barcode) {
- if (!ensureConnected()) {
- return false;
- }
- if (barcode == null || barcode.trim().isEmpty()) {
- log.info("二维码为空,无法写入VB3500");
- return false;
- }
- try {
- String code = barcode.trim();
- byte[] codeBytes = code.getBytes(StandardCharsets.US_ASCII);
- byte[] buffer = new byte[QmPlcPoint.SCAN_CODE_LENGTH];
- int copyLen = Math.min(codeBytes.length, buffer.length);
- if (codeBytes.length > buffer.length) {
- log.info("二维码长度超过VB3500容量({}字节),已截断", QmPlcPoint.SCAN_CODE_LENGTH);
- }
- System.arraycopy(codeBytes, 0, buffer, 0, copyLen);
- s7PLC.writeByte("V" + QmPlcPoint.SCAN_CODE_OFFSET, buffer);
- log.info("S7-200 SMART 写入 VB3500 二维码(ASCII): {}", code);
- return true;
- } catch (Exception e) {
- connected = false;
- log.info("写入VB3500失败: {}", e.getMessage());
- return false;
- }
- }
- /** 复位 VB3500 扫码区 */
- public static boolean clearScanCode() {
- if (!ensureConnected()) {
- return false;
- }
- try {
- byte[] empty = new byte[QmPlcPoint.SCAN_CODE_LENGTH];
- s7PLC.writeByte("V" + QmPlcPoint.SCAN_CODE_OFFSET, empty);
- log.info("S7-200 SMART 已清空 VB3500");
- return true;
- } catch (Exception e) {
- connected = false;
- log.info("清空VB3500失败: {}", e.getMessage());
- return false;
- }
- }
- private static boolean writeVBit(int byteOffset, int bitOffset, boolean value) {
- if (!ensureConnected()) {
- return false;
- }
- try {
- String address = addr(byteOffset, bitOffset);
- s7PLC.writeBoolean(address, value);
- log.info("S7-200 SMART 写入 {} = {}", address, value);
- return true;
- } catch (Exception e) {
- connected = false;
- log.info("S7-200 SMART PLC写入失败: {}", e.getMessage());
- return false;
- }
- }
- private static String addr(int byteOffset, int bitOffset) {
- return "V" + byteOffset + "." + bitOffset;
- }
- private static void ensureConnectedOrThrow() {
- if (!ensureConnected()) {
- throw new IllegalStateException("PLC未连接");
- }
- }
- }
|