自定义协议开发

    • JDK:1.8+
    • MAVEN:3.1+

    maven不要使用全局仓库配置,可能导致依赖无法下载

    • 开发工具:idea

    第一步 通过idea创建maven工程:demo-protocol

    • 修改maven pom文件properties
    1. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    2. <project.build.locales>zh_CN</project.build.locales>
    3. <java.version>1.8</java.version>
    4. <project.build.jdk>${java.version}</project.build.jdk>
    5. <netty.version>4.1.45.Final</netty.version>
    6. </properties>
    • 添加maven编译规则
    1. <build>
    2. <plugins>
    3. <plugin>
    4. <groupId>org.apache.maven.plugins</groupId>
    5. <artifactId>maven-compiler-plugin</artifactId>
    6. <version>3.1</version>
    7. <configuration>
    8. <source>${project.build.jdk}</source>
    9. <target>${project.build.jdk}</target>
    10. <encoding>${project.build.sourceEncoding}</encoding>
    11. </configuration>
    12. </plugin>
    13. </plugins>
    14. </build>
    • 添加hsweb私服和阿里云仓库

    第三步 协议开发

    • 新建packag:org.jetlinks.demo.protocol

    • 创建协议编码解码类:DemoDeviceMessageCodec

    1. import io.netty.buffer.ByteBuf;
    2. import io.netty.buffer.ByteBufUtil;
    3. import io.netty.buffer.Unpooled;
    4. import lombok.AllArgsConstructor;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.apache.commons.codec.DecoderException;
    7. import org.apache.commons.codec.binary.Hex;
    8. import org.jetlinks.core.message.DeviceMessage;
    9. import org.jetlinks.core.message.DeviceOnlineMessage;
    10. import org.jetlinks.core.message.Message;
    11. import org.jetlinks.core.message.function.FunctionInvokeMessage;
    12. import org.jetlinks.core.message.function.FunctionInvokeMessageReply;
    13. import org.jetlinks.core.server.session.DeviceSession;
    14. import org.jetlinks.wt.protocol.message.NbIotMessage;
    15. import org.jetlinks.wt.protocol.message.data.enums.DataIdEnum;
    16. import org.jetlinks.wt.protocol.message.enums.ControlEnum;
    17. import org.reactivestreams.Publisher;
    18. import reactor.core.publisher.Flux;
    19. import reactor.core.publisher.Mono;
    20. @Slf4j
    21. public class DemoDeviceMessageCodec implements DeviceMessageCodec {
    22. // 传输协议定义
    23. @Override
    24. public Transport getSupportTransport() {
    25. return DefaultTransport.TCP;
    26. }
    27. // 把tcp消息解码为平台消息,多用于设备上报消息到平台
    28. @Override
    29. public Mono<? extends Message> decode(MessageDecodeContext context) {
    30. return Mono.empty();
    31. }
    32. // 把平台消息编码为协议传输消息,多用于平台命令下发到设备
    33. @Override
    34. public Publisher<? extends EncodedMessage> encode(MessageEncodeContext context) {
    35. retrun Mono.empty();
    36. }
    37. }
    • 创建协议入口类: DemoProtocolSupportProvider
    1. import org.jetlinks.core.ProtocolSupport;
    2. import org.jetlinks.core.Value;
    3. import org.jetlinks.core.defaults.CompositeProtocolSupport;
    4. import org.jetlinks.core.device.AuthenticationResponse;
    5. import org.jetlinks.core.device.DeviceRegistry;
    6. import org.jetlinks.core.device.MqttAuthenticationRequest;
    7. import org.jetlinks.core.message.codec.DefaultTransport;
    8. import org.jetlinks.core.metadata.DefaultConfigMetadata;
    9. import org.jetlinks.core.metadata.types.PasswordType;
    10. import org.jetlinks.core.metadata.types.StringType;
    11. import org.jetlinks.core.spi.ProtocolSupportProvider;
    12. import org.jetlinks.core.spi.ServiceContext;
    13. import org.jetlinks.demo.protocol.tcp.DemoTcpMessageCodec;
    14. import org.jetlinks.supports.official.JetLinksDeviceMetadataCodec;
    15. import reactor.core.publisher.Mono;
    16. public class DemoProtocolSupportProvider implements ProtocolSupportProvider {
    17. @Override
    18. public Mono<? extends ProtocolSupport> create(ServiceContext context) {
    19. CompositeProtocolSupport support = new CompositeProtocolSupport();
    20. support.setId("demo-v1");
    21. // 协议名称
    22. support.setName("演示协议v1");
    23. // 协议说明
    24. support.setDescription("演示协议");
    25. // 物模型编解码,固定为JetLinksDeviceMetadataCodec
    26. support.setMetadataCodec(new JetLinksDeviceMetadataCodec());
    27. //TCP消息编解码器
    28. DemoDeviceMessageCodec codec = new DemoDeviceMessageCodec();
    29. // 两个参数,协议支持和编解码类DemoDeviceMessageCodec中保持一致,第二个参数定义使用的编码解码类
    30. support.addMessageCodecSupport(DefaultTransport.TCP, () -> Mono.just(codec));
    31. return Mono.just(support);
    32. }
    33. }

    第五步 平台发送消息到设备(消息编码)

    1. @AllArgsConstructor
    2. @Slf4j
    3. public class DemoTcpMessageCodec implements DeviceMessageCodec {
    4. ..........
    5. // 把平台消息编码为协议传输消息,多用于平台命令下发到设备
    6. @Override
    7. public Publisher<? extends EncodedMessage> encode(MessageEncodeContext context) {
    8. // 从平台消息上下文中获取消息内容
    9. CommonDeviceMessage message = (CommonDeviceMessage) context.getMessage();
    10. EncodedMessage encodedMessage = EncodedMessage.simple(Unpooled.wrappedBuffer(message.toString().getBytes()));
    11. // 根据消息类型的不同,构造不同的消息
    12. if (message instanceof ReadPropertyMessage) {
    13. ReadPropertyMessage readPropertyMessage = (ReadPropertyMessage) message;
    14. // 获取需要传输的字节
    15. byte[] bytes = readPropertyMessage.toString().getBytes();
    16. // 构造为平台传输到设备的消息体
    17. encodedMessage = EncodedMessage.simple(Unpooled.wrappedBuffer(bytes));
    18. }
    19. return Mono.just(encodedMessage);
    20. }
    21. }

    进行协议上传和 配置,并使用TCP工具进行测试。

    注意

    建议在编写协议包时,先用单元测试进行测试。最后再发布到平台进行模拟设备测试。

    调试(debug)协议

    参照目录:

    1. --jetlinks
    2. ----|--dev
    3. ----|---|-- demo-protocl # 开发中的协议
    4. ----|--jetlinks-components

    注意

    在调试过程中修改代码可以进行热加载,但是重启服务后会失效,需要重新发布协议.