tt协议号服务器,TTIot: TTIoT云端物联网Iot组件;面向JAVA;netty;mqtt;异步推送;以事件为驱动;为设备提供安全可靠的连接通信能力;...

80a857bcfe581ce1c7f28964991b7eea.png

TTIoT云端物联网组件;面向JAVA;以事件为驱动;为设备提供安全可靠的连接通信能力

TTIot.svg?branch=master

License-Apache--2.0-brightgreen.svg

community.svg

TTIoT简介

TTIOT的Broker采用MQTT协议与设备进行交互,可以应用在数据采集、能源监控、智能生活、智能工业、农业水利等场景;

向下提供连接海量设备服务,支撑设备数据采集上云,支持M2M;无侵入集成第三方服务端,提供事件API,实现远程控制设备;此外,TTIOT将会持续开源物联网套件,如多协议引擎、设备管理、规则引擎、数据分析等插件为各类IoT场景和行业开发者赋能。

Broker组件,TTIot把TCP/IP协议族上的协议都转换成了事件池,开发者只需要面向事件编程即可。

5476d49226752fb3884a9756409c05cd.png

2.1版本重要更新

增加SSL加密功能,同时支持https\wss\tls协议

在配置文件添加

ssl:

enabled: true

certificateType: PKCS12

certificatePath: /Users/shijun/Desktop/TTIOT/ca/server/3938.pfx

certificatePassword: 5J7HDiJM

2.0版本重要更新

多协议转换引擎-一个端口支持三种协议HTTP/WEBSOCKET/TCP,上层协议使用的依然是MQTT,支持使用这三种不同协议的客户端相互通信(详见使用说明.10)

使用HTTP协议向设备投递消息,URI:/mqtt,请求体如下:

Headers:userName //设备帐号

tenantId //租户编号

password //设备密码

Body:

{

"mqttQos": 1, //消息质量

"payload": { //消息体

"rule": "chat",

"content": "hello"

},

"retain": false, //是否为retain消息

"topic": "/m" //推送的话题

}

支持消息路由引擎@Ruler-给消息定义规则(详见使用说明.12)

功能

认证授权(auth)

TTIoT的容器对发布的事件都会自动检查登陆状态,对未授权的设备进行自动拦截,只要在相关的类添加@Eventor(auth = true)即可

@Eventor(value = AppProtocalMqttConstant.PINGREQ,auth = true)

public class MqttPingEvent extends MqttApplicationEvent {

public MqttPingEvent(MqttMessage msg, ChannelHandlerContext context) {

super(msg, context);

}

}

多租户(saas)

TTIot的设备归属为租户,其devName与topic对每个租户唯一,clientId构成为:tenantId-devName-xxxx(保留字段);并且提供接口将设备进行录入,例如

dbHelper.saveTenant(tenant);

dbHelper.saveDev(device);

控制反转(IOC)

TTOT放弃第三方框架IOC框架,内部维护了一个轻量的容器,在项目启动时对所有的Listener扫描并且接管

消息的订阅与发布(Qos)

(1)支持Qos(Quality of Service)

TTIot提供mqtt三种消息质量模型即:

Qos0:最多一次的传输

Qos1:至少一次的传输

Qos2:只有一次的传输

该方案适应任何网络场景,特别是网络较差的场景

(2)通配符与消息降级

TTIot提供主题层级分隔符/,单层通配符+,多层通配符#,设备实现灵活订阅

心跳检测(Idle)

TTIot 提供两种测活机制

(1)服务端定义

TTiot:

heartbeatTimeout: 10

(2)客户端通过设置可变头里面的keepAliveTimeSeconds定义

保留消息与消息遗嘱

(1)Topic只有唯一的retain消息,Broker会保存每个Topic的最后一条retain消息;每个Client订阅Topic后会立即读取到retain消息,不必要等待发送。订阅Topic时可以使用通配符,就会收到匹配的每个Topic的retain消息;发布消息时把retain设置为true,即为保留信息。

(2)MQTT本身就是为信号不稳定的网络设计的,所以难免一些客户端会无故的和Broker断开连接;当客户端连接到Broker时,可以指定LWT,Broker会定期检测客户端是否有异常;当客户端异常掉线时,Broker就往连接时指定的topic里推送当时指定的LWT消息。

使用说明

配置文件

配置文件延续了yaml风格,默认命名为TTIotBootstrap.yml,在自己模块resources目录下添加TTIotBootstrap.yml文件即可

TTiot:

port: 8726 #端口

heartbeatTimeout: 10 #心跳间隔时间

netty:

bossGroupCount: -1 #-1代表线程数量取决于cpu

workerGroupCount: -1 #-1代表线程数量取决于cpu,此参数决定了netty的worker线程与TTIot内置的核心线程

redis: #redis相关

项目启动

8af404d7d011c769052f1b79c4be6e21.png

new ServerLauncher().launch();

自定义数据源

(1) 实现DbHelper接口

(2) 添加数据源插件,Broker提供默认的redis实现

new ServerLauncher().dbHelper(new RedisDbHelper(new RedisSourceProvider())).launch();

自定义统一异常处理器

(1) 继承ExceptionHandlerAdapter,或者实现 Thread.UncaughtExceptionHandler 接口

(2) 添加异常处理插件,Broker提供默认的ExceptionHandlerAdapter实现

new ServerLauncher().exceptionHandler(new ExceptionHandlerDemo()).launch();

依赖注入

由于Listener是由TTIot接管的,在Listener内部系统提供了两种级别的注入方式,选择需要注入的对象添加@Inject注解即可

(1)service 注入

@Listener(asynchronous = true)

public class LoginLogListener extends MqttApplicationListener {

@Inject

private SessionService sessionService;

}

(20 dao 注入

public class DeviceService{

@Inject

private DbHelper dbHelper;

}

自定义消息处理器

TTIot 提供@Listener 注解来处理具体的事件信息,在@Listener里面有两个参数

replace 为true时,替换该事件的默认处理器,为false时,对该事件新增一个处理器

asynchronous 为true时,申明该处理器为一个异步处理器,由TTIot内置的线程池进行接管,线程池大小由TTiot:netty:bossGroupCount 决定,为false时,由netty 的EventLoopGroup 接管;

处理器可以用来实现额外的功能,并且跟默认业务解耦,例如,异步的设备登陆日志

@Listener(asynchronous = true)

public class LoginLogListener extends MqttApplicationListener {

@Override

public void onApplicationEvent(MqttConnectEvent mqttConnectEvent) {

DbDemo.saveLogin(mqttConnectEvent.getTimestamp(), mqttConnectEvent.getDevName(), mqttConnectEvent.getTenantId());

}

}

无侵入设计

如果开发者想自定义事件的默认处理逻辑,无需修改源码,只需要加上如下注解上即可,TTot则会更换默认的处理逻辑,开发者也可以利用TTot的事件驱动,自定义事件

@Listener(replace = true)

事件发布

TTIot 提供多种默认的事件供开发者使用,给topic推送消息,例如

Context.me().publishEvent(new MqttPublishTopicEvent(String topic,MqttQoS mqttQoS,byte[] bytes,String tenantId,boolean isRetain);

例如,给device单独推送消息

Context.me().publishEvent(new MqttPublishDevEvent(String clientId, String topic, byte[] byteBuf, MqttQoS qoS,String tenantId);

docker-compose

首先,需要安装git与docker

git clone https://gitee.com/cloudSj/TTIot.git

cd 到项目根目录

mvn clean install

mvn clean install package -Dmaven.test.skip

docker-compose up -d

webSocket接入

TTIOT内置了webSocket协议转换器,开发者只需要关注业务逻辑,无需关注协议处理、转换层面的相关问题。

HTTP接入及设备控制

TTIOT目前只接受POST类型的请求,格式如下:

URI:/mqtt

Headers:userName //设备帐号

tenantId //租户编号

password //设备密码

Body:

{

"mqttQos": 1, //消息质量

"payload": { //消息体

"rule": "chat",

"content": "hello"

},

"retain": false, //是否为retain消息

"topic": "/m" //推送的话题

}

HTTP由于协议本身的特性只支持QOS类型为1或2

规则路由@Ruler

如果消息的内容符合

{

"rule": "chat",

"content": "hello"

}

消息格式,TTIOT将自动触发规则路由器,将消息自动投递到与rule值对应的处理器上如:

@Ruler(name = "chat")

public class ChatRuleHandler implements RuleHandler {

@Override

public void handler(MqttPayloadVo mqttPayloadVo) {

System.out.println(mqttPayloadVo);

}

}

因此,开发者可以自定义业务处理逻辑

TTIoT 开源计划

docker部署组件

HTTP组件以及控制设备HTTPAPI

物模型组件

网关\集群与分布式扩展组件

安卓端组件

规则引擎组件(后续将会持续更新)

SSL加密传输

另外:作者诚邀开发人员提交下位机例如PLC/单片机/安卓相关代码,如有计划者可以通过邮箱跟作者取得联系

联系作者

关注公众号:(不定期推送关于IoT的干货以及源码解析)

感谢:lombok、netty、hutool 提供的工具以及源码

参与贡献

Fork项目到自己的repo

clone到本地

修改代码(dev分支)

commit后push到自己的库(dev分支)

pull request

等待作者合并

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python圆面积函数_Python基础函数必学

S πr2 当我们知道半径r的值时,就可以根据公式计算出面积。假设我们需要计算3个不同大小的圆的面积: r1 12.34 r2 9.08 r3 73.1 s1 3.14 * r1 * r1 s2 3.14 * r2 * r2 s3 3.14 * r3 * r3 当代码出现有规律的重复的时候,你就需要当心了…

javamail发送html正文文件_Python实现-生成测试报告amp;自动邮件发送

之前单独介绍了生成测试报告和自动发送邮件,那么现在把两者整合到一起;生成测试报告后然后自动发送邮件,这里只是简单的整合实现功能,其实还可以优化的,先用吧,后面再慢慢优化先看下目录,其实目…

笨方法学python3怎么样_有个很笨的女朋友,是怎么样的体验?

我是妹子 ,但是我并不觉笨是可爱. 反而觉得自己是累赘。 为什么别人可以思考过来的东西, 我却需要很费劲? 为什么 ?我的逻辑思维能力很差? 我没有感觉到自己是可爱 ,甚至感到自卑。 一提到学习,…

byte转换为string乱码_每日一课 | 如何将int转换为String

在Python中&#xff0c;我们可以使用str()将int转换为String。num1 100print(type(num1)) # int> num2 str(num1) print(type(num2)) # str>输出量<class int><class str>参考文献&#xff1a;Python文档– str()Python –如何将String转换为int翻译自: ht…

openssh升级后root_又一root神器停止营业!时至今日你还需要root吗

[PConline杂谈]最近&#xff0c;一条新闻引起了安卓玩家们的注意——360超级root宣布停止运营。在此前&#xff0c;也已经有其他知名root工具和玩家们渐行渐远&#xff0c;例如SuperSu开发者宣布停止开发所有root应用。除了root工具停止开发&#xff0c;root机在用户群中的热度…

MyBatis中or和and的使用问题

在使用or和and混合使用时&#xff0c;name成立并且想要age和bj其中一个成立就显示&#xff0c;这样写&#xff1a; QueryWrapper userWrapper new QueryWrapper(); userWrapper.eq(“name”, name); userWrapper.eq(“age”, age).or().eq(“bj”, bj); 出来的sql语句&#…

python设置excel的格式_python使用xlrd与xlwt对excel的读写和格式设定

前言 python操作excel主要用到xlrd和xlwt这两个库&#xff0c;即xlrd是读excel&#xff0c;xlwt是写excel的库。本文主要介绍了python使用xlrd与xlwt对excel的读写和格式设定&#xff0c;下面话不多说&#xff0c;来看看详细的实现过程。 脚本里先注明# -*- coding:utf-8 -*- 1…

dijkstra算法代码_深度好文:改变了我们生活方式最有影响力的5种图算法

作者&#xff1a;Rahul Agarwal编译&#xff1a;刘静图灵联邦编辑部出品本文作者Rahul Agarwal是一位数据科学家&#xff0c;近期&#xff0c;他在Medium上分享了常用的5种图算法的介绍和代码实现。以下是具体博文内容&#xff1a;作为数据科学家&#xff0c;我们已经对Pandas或…

使用equals判断对象是否相等出现的错误

我在使用中 if(a.equals(b)&&a!null) 这样使用如果a是null&#xff0c;a.equals&#xff0c;抛出NullPointException异常&#xff0c;不会进行下一步 应该这样写 if(a!nuull&&a.equals(b)) 先保证a不等于null&#xff0c;再用a.equals&#xff0c;来判断他…

laravel5.6 使用指定字段作为key_MyRocks TTL使用姿势及Bugfix

一些业务场景是经过一段时间后删除过期的数据&#xff0c;MyRocks提供了TTL可以满足该场景。MyRocks 通过Compaction回收过期的数据。本文介绍MyRocks TTL使用姿势以及Bugfix。TTL 通过 table comment 定义&#xff0c;有两种形式&#xff1a;CREATE TABLE t1 (a INT, b INT, c…

a==b和a.equals(b)的区别

使用ab时 如果a和b都是对象时&#xff0c;是进行对象地址的判断&#xff0c;假如a和b指向的是堆中同一个对象才会返回ture 如果是字符串&#xff0c;会比较他们的值是否相等 使用a.equals(b)时 如果是对象&#xff0c;首先&#xff0c;进行了对象地址的判断&#xff0c;如果…

mybatis更新时间字段_你以为把Mybatis型处理器了解了,就不会“暴雷”了!

1. 明确需求在设计之初&#xff0c;sys_role表的enabled字段有2个可选值&#xff0c;其中0 代表禁用&#xff0c;1代表启用&#xff0c;而且实体类中我们使用的是Interger类型&#xff1a;/*** 有效标志*/ private Integer enabled;public Integer getEnabled() {return enable…

filter函数使用出现的问题

需求&#xff1a; 需要在筛选框中&#xff0c;输入筛选条件&#xff0c;筛选出当前列表中符合的数据。 indexList&#xff1a;[] 是数组存储的数据e是获取输入框中的值 query(e){this.indexListthis.indexList.filter(function (item) {return item.goodsname.indexOf(e) ! -…

python根据模板生成pdf文件_程序生成word与PDF文档的方法(python)

程序导出word文档的方法 将web/html内容导出为world文档&#xff0c;再java中有很多解决方案&#xff0c;比如使用Jacob、Apache POI、Java2Word、iText等各种方式&#xff0c;以及使用freemarker这样的模板引擎这样的方式。php中也有一些相应的方法&#xff0c;但在python中将…

js将object转化为json数据,json数据转js对象

json数据转js对象: JSON.parse(); js对象转json数据: JSON.stringify();

本地更新github项目_GitHub开源项目2019-03-29更新精选

1.etcd&#xff1a;一个高可用的分布式键值数据库&#xff0c;k8s 全家桶标配的注册与发现服务etcd&#xff1a;一个高可用的分布式键值数据库&#xff0c;k8s 全家桶标配的注册与发现服务。它采用 raft 一致性算法&#xff0c;基于 Go 语言实现。可以通过该项目了解、学习 raf…

js中for循环调用回调函数,一直循环最后一个

js的for循环中使用回调函数&#xff0c;获取到的值总是最后一个值&#xff1f;_MLAY-CSDN博客_js 循环回调函数

maven default aliyun_大家看看大佬对Maven仓库的讲解,有何高明之处?

概念Maven在某个统一的位置存储所有项目的共享的构件&#xff0c;这个统一的位置&#xff0c;我们就称之为仓库。(仓库就是存放依赖和插件的地方)。分类maven的仓库只有两大类&#xff1a;1.本地仓库 2.远程仓库&#xff0c;在远程仓库中又分成了3种&#xff1a;中央仓库、 私服…

形参和实参的区别

形参就是函数声明时的变量&#xff0c;实参是我们调用该函数时传入的具体参数。 function function(a,b){ console.log(a,b) }function(1,2) 这里1&#xff0c;2就是实参 a,b是形参