All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iteaj.iot.modbus.server.dtu.ModbusRtuMessageAware Maven / Gradle / Ivy

There is a newer version: 3.1.1
Show newest version
package com.iteaj.iot.modbus.server.dtu;

import com.iteaj.iot.modbus.consts.ModbusCode;
import com.iteaj.iot.modbus.consts.ModbusErrCode;
import com.iteaj.iot.server.dtu.DefaultDtuMessageAware;
import com.iteaj.iot.server.dtu.DtuCommonProtocolType;
import com.iteaj.iot.server.dtu.DtuMessageType;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

public class ModbusRtuMessageAware extends DefaultDtuMessageAware {

    public ModbusRtuMessageAware() { }

    public ModbusRtuMessageAware(DtuMessageType messageType) {
        super(messageType);
    }

    /**
     * 校验是否是标准的modbus协议
     * @see ModbusRtuForDtuServerComponent#doTcpDecode(ChannelHandlerContext, ByteBuf)
     * @param equipCode
     * @param message
     * @param msg
     * @return 如果是标准的modbus rtu协议返回 {@code null} 否则返回dtu私有协议 {@link DtuCommonProtocolType#DTU}
     */
    @Override
    protected M customizeType(String equipCode, byte[] message, ByteBuf msg) {
        // modbus rtu 协议报文长度不能小于2
        // 小于5说明是dtu的报文
        if(message.length < 3) {
            return null; // 不能判断, 等待下一个报文
        }

        // 获取modbus tcp的功能码
        int code = message[1] & 0xFF;
        if(code > 0x80) { // 读取到的功能码可能是modbus的异常码, 异常码大于 0x80
            code = code - 0x80;
            try {
                ModbusCode.INSTANCE((byte) code);
                ModbusErrCode.valueOf(message[2]);

                if(message.length < 5) {
                    return null; // 等待下一个报文
                }

                // 读取5个字节的modbus异常报文
                return createMessage(5, msg);
            } catch (IllegalStateException e) {
                return createMessage(DtuCommonProtocolType.DTU, msg);
            }
        }

        // modbus的功能码只能是在 0x01 - 0x10之间
        if(code >= 0x01 && code <= 0x10) {
            try {
                ModbusCode.INSTANCE((byte) code);
                // todo 以下的长度判断:如果对于一个标准的modbus报文拆分成两包则会出现校验成DTU包的问题
                // 所以在读取报文时读取的寄存器数量尽量少 不要太多导致一个报文拆成两个
                if(code <= 0x04) { // 读报文校验
                    int length = message[2] & 0xFF;
                    if(message.length < length + 5) {
                        return null;
                    } else {
                        // 读取rtu报文
                        return createMessage(length + 5, msg);
                    }
                } else { // 写报文校验
                    if(message.length < 8) {
                        return null;
                    } else {
                        // 读取rtu报文
                        return createMessage(8, msg);
                    }
                }
            } catch (IllegalStateException e) { // 不是modbus协议的功能码
                return createMessage(DtuCommonProtocolType.DTU, msg);
            }
        } else { // 不存在功能码说明不是modbus协议
            return createMessage(DtuCommonProtocolType.DTU, msg);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy