JetLinks平台二次开发 : 一、TCP设备接入JetLinks平台

jetlinks是一个开源的物联网云平台,功能比较强大。支持MQTT、TCP、COAP、HTTP等设备的接入,若要在平台中接入设备,可根据此文档进行相关操作。

关于该平台的基本信息,这里不做过多介绍,详细功能附上链接 JetLinks 物联网基础平台(2.x) 

后续将出一系列在该平台做接入设备涉及的MQTT、TCP协议开发、数据qingqi的博客,欢迎大家评论交流。

要做该平台的接入,首先了解官网,下载源码,安装依赖环境,相关环境后端包括Java、jdk 1.8及以上、IDEA、redis、elasticsearch、当然数据库也是必须的,前端安装node,更新yarn即可,这里不做过多介绍,上述环境推荐docker安装,简单方便。

这里附上源码链接:https://gitee.com/jetlinks/jetlinks-communityJetLinks物联网基础平台 - JetLinks物联网基础平台https://gitee.com/jetlinks/jetlinks-community

注: 图中左图后端代码(模块较多,目前仍在学习中,后续介绍),右图前端代码。

### 1. 环境安装和平台本地部署

安装完软件,下载完代码后,下一步便是部署前后端项目,当然官网也有说明,这里以本人在做时的截图给大家呈现,没问题可以跳过。

先运行后端代码,打开后端模块 jetlinks-standalone

->配置redis,根据自己安装的redis真实信息进行配置

->配置数据源

 ->配置elasticsearch

 运行模块jetlinks-standalone下启动类JetLinksApplication

 至此,后端启动成功!

接下来是前端,打开node命令行工具

进入前端代码所在目录,这里我是E盘下的目录

修改配置文件config/proxy.ts,本人局域网内主机IP为以下地址,上面运行后端端口8848,以下配置让 前端访问的地址指向到我们刚运行的后端项目。

 

根据官网启动说明文档,运行yarn dev 

 可能出现如下。

网上搜索说是版本不一致,本人前端小菜鸡,按大神指示照做,果然正确

> set NODE_OPTIONS=--openssl-legacy-$ npm run start:dev

 运行测试

 至此,本地部署实现。

### 2. TCP协议的设备接入

步骤一  jetlinks平台中配置

​ 设备管理下,配置 产品->设备

​ 运维管理下,配置设备接入网关-> 网格组件 -> * 协议管理 *(这里需要做协议开发)

这些配置根据官方文档都能完成,这里介绍下易掉坑的几个地方。

FQ1: 第一个,配置协议时的公网地址为TCP客户端发起访问时,需要连接的地址,公网地址为当前服务器的IP。

FQ2:第二个,协议管理时,协议怎么选?

从官网JetLinks物联网基础平台/jetlinks-official-protocol下载代码,package中已经为我们提供了可用的协议jar包,但这个协议包的通信过程,报文数据需按平台的格式来发送。

协议管理下,选择协议,上传jar包时,可直接选我们刚下载package目录下的协议jar包。 

特别注意,官网协议包里,这里是客户端向服务器发送数据时,每一次都会被调用的地方,包括发送建立连接的报文,这里如果有执行readInt,那么报文数据前就需要带上4个字节的数据长度。

 

步骤二 支持自定义TCP的协议开发

idea下,打开jetlinks-official-protocol工程,默认包路径 org.jetlinks.protocol.official.tcp 下,这里有几个关键类,若要做开发,可看了这些类的代码后,进行编写修改。


1.tcp/TcpDeviceMessageCodec:tcp设备连接后,发送数据时,平台会调用的解析类,设备发送的数据将该 类中的decode方法进行解析,因此处理自定义数据时,接收客户端发送数据的入口在这里。

    @NonNull
    @Override
    public Publisher<? extends Message> decode(@NonNull MessageDecodeContext context) {
​
        ByteBuf payload = context.getMessage().getPayload();
        //read index
//        payload.readInt();
​
//        处理tcp连接后的首次消息
        if (context.getDevice() == null) {
            return handleLogin(payload, context);
        }
        System.out.println("zhouxiong-test:"+context);
        System.out.println("zhouxiong-test:"+context.getDevice());
        return Mono.justOrEmpty(BinaryMessageType.read(payload, context.getDevice().getDeviceId()));
    }

2. binary/BinaryMessageType: 上述decode方法调用后,会通过该枚举中的read方法,这里我简单做了条件分支处理,根据获取的数据报文长度,判断数据长度未超过47为平台的正常报文,超过47的话,认为该报文不是jetlinks平台默认报文格式

 

public static DeviceMessage read(ByteBuf data, String deviceIdMaybe) {
    int bytsLen = data.readableBytes();
    //执行报文数据解析后的回调方法
    BiFunction<DeviceMessage, Integer,DeviceMessage>  bf = (message, msgId) -> {
        String messageId = null;
        if (message.getDeviceId() != null) {
            //获取实际平台下发的消息ID
            MsgIdHolder holder = cache.get(message.getDeviceId());
            if (holder != null) {
                messageId = holder.getAndRemove(msgId);
            }
        }
        if (messageId == null && msgId > 0) {
            messageId = String.valueOf(msgId);
        }
        message.messageId(messageId);
        return message;
    };
    //接收到的数据长度若超过47,则此次报文长度为厂家报文,否则是标准报文
    if(bytsLen<47)
        return read(data, deviceIdMaybe, bf);
    else
        return read_silk(data, deviceIdMaybe, bf);
}

3.测试类test.java.official.binary.BinaryMessageTypeTest

该类下有几个测试方法,生成符合JetLinks官方的报文数据,模拟TCP数据通信时,客户端需要传递这种数据向服务端发送报文,主要有以下请求:

  • 设备上线->testOnline,方法中的设备号和授权码需根据实际信息进行修改

  • 数据上报->testReport,同上

  • 数据读/写等,此处未涉及到,不做介绍

设备上线方法testOnline

public void testOnline() {

    DeviceOnlineMessage message = new DeviceOnlineMessage();
    message.setDeviceId("1004");
    message.addHeader(BinaryDeviceOnlineMessage.loginToken, "admin");
    ByteBuf byteBuf = BinaryMessageType.write(message, Unpooled.buffer());
    System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
    System.out.println(ByteBufUtil.prettyHexDump(Unpooled
                                                          .buffer()                              
                                    .writeInt(byteBuf.readableBytes())
                                                          .writeBytes(byteBuf)));

 上述testOnline报文为:01 00 00 01 87 a3 2b fb 16 ff ff 00 04 31 30 30 34 00 05 61 64 6d 69 6e,通过网络调试助手工具,即可模拟TCP设备上线,连接后以十六进制方式发送该数据,即完成设备上线命令!


设备数据上报testReport

@Test
 public void testReport() {
     ReportPropertyMessage message = new ReportPropertyMessage();
     message.setDeviceId("1001");
     message.setMessageId("test123");
     message.setProperties(Collections.singletonMap("temperature", 37.6));

     doTest(message);

上述报文为:03 00 00 01 87 a3 30 92 d7 00 01 00 04 31 30 30 31 00 01 00 0b 74 65 6d 70 65 72 61 74 75 72 65 0a 40 42 cc cc cc cc cc cd,通过网络调试助手工具,发送上线命令后,以十六进制方式发送上述命令,即完成1001设备数据上报,上报温度为37.6!

测试,新增一个产品,名称为:测试TCP通信,连接信息本机局域网地址,端口为1887,secureKey为admin.

新增设备,所属产品为刚刚新增的产品,注意需要启动上述产品

在该产品下新增物模型->温度传感器,配置如图

 最后,记得启用该设备,这里不截图了

### 3.TCP通信测试

打开网络调试助手,配置访问的远程主机IP和端口,发送区勾选“按十六进制发送” 

网络调试助手打开了,发送连接的报文数据怎么写呢?

网络调试助手先放着,打开协议包代码,代码的测试包下,testOnline方法中,将deviceID和logintoken的值改为我们前面配置的信息,这里我的设备ID为DV001,改好后运行测试方法,输出报文如下。

 输出的第二段报文为带上长度信息的报文,这里不用,为什么不用?因为我们前面在解码方法中decode里注释了readInt方法。

 

闲话少说, 来,看测试结果,调试助手中点击连接,此时助手和服务端建立Socket连接

 点击发送,发送设备上线报文给服务端,此时网页中DV001设备正式上线

 至此,设备上线接入成功。那么,数据上报可以吗?

 打开协议包代码,修改设备ID和温度数据,运行测试代码,得到生成报文(见控制台)

 将控制台中报文数据拷贝到调试助手中

 点击发送,走你!

 我们刚刚上报的温度数据便到达平台!

最后,作者是工作了几年的程序员小白,欢迎大佬批评指正!创作不易,如果有用,恳请点赞评论支持一下!

后续针对JetLinks平台,将继续退出关于该平台的协议开发和源码开发相关文章!

 

 

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
JetLinks开源物联网平台基于Java8、Spring Boot 2.x、WebFlux、Netty、Vert.x、Reactor等开发,是一个开箱即用,可二次开发的企业级物联网基础平台平台实现了物联网相关的众多基础功能,能帮助你快速建立物联网相关业务系统。 JetLinks开源物联网平台核心特性: 支持统一物模型管理,多种设备,多种厂家,统一管理。 统一设备连接管理,多协议适配(TCP、MQTT、UDP、CoAP、HTTP等),屏蔽网络编程复杂性,灵活接入不同厂家不同协议的设备。 灵活的规则引擎,设备告警,消息通知,数据转发。可基于SQL进行复杂的数据处理逻辑。 地理位置:统一管理地理位置信息,支持区域搜索。 数据可视化:实现拖拽配置数据图表,设备组态等。 JetLinks开源物联网平台技术栈: Spring Boot 2.2.x Spring WebFlux 响应式Web支持 R2DBC 响应式关系型数据库驱动 Project Reactor 响应式编程框架 Netty、Vert.x 高性能网络编程框架 ElasticSearch 全文检索,日志,时序数据存储 PostgreSQL 业务功能数据管理 hsweb framework 4 业务功能基础框架     JetLinks开源物联网平台 更新日志: v1.9 1、增加设备独立物模型支持,可给单独的设备配置物模型. 2、基本实现GB28181国标视频设备接入,支持直播,云台控制,级联操作.(选配模块) 3、RabbitMQ增加routeKey配置,可在配置文件中指定device.message.writer.rabbitmq.consumer-route-key和device.message.writer.rabbitmq.producer-route-key.(Pro) 4、当设置了device.message.writer.rabbitmq.consumer=false时,不创建MQ消费者.(Pro) 5、设备支持独立物模型,可单独配置设备的物模型. 6、适配tdengine 2.0.16.0,优化sql长度策略. (pro) 7、优化规则引擎编辑器,实现组件模块化动态加载.(Pro) 8、修复启动服务时,如果某个产品物模型发布失败,导致后面的产品终止发布的问题. 9、增加ignoreLatest消息头,message.addHeader("ignoreLatest",true) 忽略记录最新数据到数据库. 10、修复租户下操作设备告警提示无权限.(Pro) 11、优化租户在解绑成员时,同时解绑成员的资产信息.(Pro) 12、优化子设备消息回复处理 13、物模型属性增加存储方式功能,可配置部分属性不存储. 14、增加虚拟属性功能,可通过规则来计算出虚拟属性值.(Pro) 15、增加租户成员绑定(TenantMemberBindEvent),解绑(TenantMemberUnBindEvent)事件.可通过spring-event订阅处理此事件.(Pro) 16、优化子设备状态检查,当检查子设备状态时,将会尝试发送ChildDeviceMessage<DeviceStateCheckMessage>给网关,处理后返回ChildDeviceMessageReply<DeviceStateCheckMessageReply>. 17、增加ClickHouse设备数据存储策略支持.(Pro) 18、增加权限过滤功能,可配置禁止赋予自己没有的权限给其他用户.hsweb.permission.filter相关配置 19、设备和产品的租户绑定逻辑优化: 绑定设备时,自动绑定产品.解绑产品时,自动解绑设备.(Pro) 20、用户管理增加租户权限控制.(Pro) 21、当向keepOnline的设备发送消息时,如果原始连接已断开,将返回CONNECTION_LOST错误. 22、设置keepOnline的会话将被持久化,重启服务后自动恢复.(Pro) 23、默认关闭设备最新数据存储,通过jetlinks.device.storage.enable-last-data-in-db=true开启.(Pro) 24、属性物模型增加属性值来源,配置为手动时,在发送修改属性指令(WritePropertyMessage)时,将直接生效,不会发送到设备. 25、优化租户资产解绑逻辑,当删除数据时,解绑资产全部的绑定关系.(Pro) 26、用户管理,机构管理增加租户端支持,租户可以自己管理自己的用户和机构.(Pro)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值