Mainflux 学习笔记

  Mainflux是一个由法国的创业公司开发并维护的开源的物联网云平台,Mainflux使用Go语言、微服务的框架。Mainflux支持多种接入设备,包括设备、用户、APP;支持多种协议,包括HTTP、MQTT、WebSocket、CoAP,并支持他们之间的协议互转。
  Mainflux的南向接口连接设备,北向接口连接应用,提供一个完整的从设备端到平台到应用的解决方案。

概述

Mainflux提供以下服务:

  • 在设备和应用之间提供消息的扭转,包括HTTP、MQTT、WS、CoAP;
  • 系统管理;
  • 设备管理-南向接口;
  • 应用管理-北向接口;
  • 用户管理;
  • 数据存储-时序数据库;
  • 复杂的消息处理,基于系统事件总线NATS,通过规则引擎,根据时间数据流进行事件触发;

开源物联网系统 java 开源物联网平台_HTTP

消息扭转及协议转换

Mainflux能够实现设备与应用之间的通信,完成消息的上传及消息的下发;或者设备与设备,应用与应用之间的通信。

系统管理

  • 用户
    用户是指使用Mainflux的人员,包括多个角色(管理员、应用创建者、开发人员),这些角色如果有权限,将会管理设备、应用以及channel。
  • 客户端
    客户端主要分两类,一类是设备;一类是应用;
  • 设备
    设备主要是功耗受限、内存受限、计算能力受限的一些设备,这类设备倾向于使用MQTT、CoAP协议,在加密手段上使用DTLS而不是TLS,对于这类设备Mainflux主要提供MQTT以及CoAP来连接设备。对于一些运算资源丰富的设备,提供HTTP、WebSocket协议。
  • 应用
    应用主要运行在业务服务器,应用的连接主要通过HTTP REST或者WebSockets,可以双向通信。当然,应用也可以选择MQTT或者CoAP这些协议。
  • 通道(连接)
    通道是Mainflux中的重要的通信模型,它是对双向消息流的一个表述,可以把他理解为连接,具体表现就是MQTT的topics,设备和应用可以在一个消息通道上订阅或发布topic。所有流过通道的数据流都会在数据库总持久化。
  • 设备管理
    Mainflux提供了用于描述系统中设备的模型,模型能够表征设备的状态。每一个连接到Mainflux的设备在数据库中都拥有他们自己的模型,这些由设备自己更新。如果一个设备需要更新状态,直接发送UPDATE的请求给Mainflux即可,这个更新对于需要获取其信息的应用端或者其他设备也会得到更新,反之亦然。
    Mainflux维护者所有的这些内部设备模型,保持连接,并管理这些设备,获取他们的信息:
  • 连接了多少设备;
  • 他们分布在哪里;
  • firmware的版本是多少;
  • 电池的状态怎么样;
  • 设备的序列号是什么;
    Mainflux还可以发送各种各样的指令给设备:
  • 打开或关闭设备;
  • OTA升级;
  • 设备分组或者更换访问权限;
  • 用户和应用管理
    Mainflux是一个多用户和多组织的应用管理平台。Mainflux的开发者可以创建基于Mainflux的多用户应用,而不需要自己管理这些用户,也即是说Mainflux可以帮助应用管理用户。(文中说类似于Twitter的应用创建流程)

时序数据库

Mainflux使用NoSQL分布式数据库Cassandra来存储事件数据,工业IoT更多是仪表数据,这些能够很好的帮助数据存储,以及可以进行快速的复杂查询。

时间处理引擎

Complex Event Processing (CEP)是用于跟踪和分析数据流的方法,并得到一些结论。Mainflux使用Spark来进行数据转换,使用Cassandra来作为存储介质。

事件处理及系统Dashboard

Mainflux的消息子系统是一个异步的事件系统处理来自传感器以及应用的消息。消息机制使用NATS,使用pub/sub机制。
Mainflux通过NATS形成了一个消息转换中心,也就是说订阅一个MQTT的topic能够收到来自HTTP POST关于同样topic的消息。
同时,NATS会通过Writer的微服务来接收这些事件,并以合适的格式存储到Cassandra数据库。
Mainflux的消息格式使用SenML 语法,这是一个标准的消息模型。

SenML

SenML是一个IETF标准 ,其提供了一个简单模型用来接收传感器的数据,以及控制一些设备。SenML能够通过最小的语句以及一些扩展和链接来表征数据和元数据(metadata)。
示例

[
  {
    "bn" : "urn:dev:ow:10e2073a0108006;",
    "bt" : 1.276020076001e+09,
    "bu":"A",
    "bver" : 5,
    "n" : "voltage",
    "u" : "V",
    "v" : 120.1
  },
  {"n" : "current", "t" : −5, "v" : 1.2},
  {"n" : "current", "t" : −4, "v" : 1.3},
  {"n" : "current", "t" : −3, "v" : 1.4},
  {"n" : "current", "t" : −2, "v" : 1.5},
  {"n" : "current", "t" : −1, "v" : 1.6},
  {"n" : "current", "v" : 1.7}
]

Mainflux Message

Mainflux使用下面的格式对来自传感器的SenML数据进行封装:

type RawMessage struct {
   Channel string `json:"channel"`
   Publisher string `json:"publisher"`
   Protocol string `json:"protocol"`
   ContentType string `json:"content_type"`
   Payload []byte `json:"payload"`
}

Normalization

Mainflux的Writer微服务订阅了NATS的来自协议转换中心的的所有事件。Writer微服务接收的消息使用Mainflux的内部消息格式,解析这些RAW数据,得到有用的SenML载荷。
对这些SenML的进行聚合能够标准化为时间序列消息,Writer微服务负责处理SenML的标准化,并写入时序数据库。
最终写入数据库的内容

type Message struct {
	Channel string
	Publisher string
	Protocol string
	Version int `json:"bver,omitempty"`
	Name string `json:"n,omitempty"`
	Unit string `json:"u,omitempty"`
	Value float64 `json:"v,omitempty"`
	StringValue string `json:"vs,omitempty"`
	BoolValue bool `json:"vb,omitempty"`
	DataValue string `json:"vd,omitempty"`
	ValueSum float64 `json:"s,omitempty"`
	Time float64 `json:"t,omitempty"`
	UpdateTime float64 `json:"ut,omitempty"`
	Link string `json:"l,omitempty"`
}

Security

Mainflux 基于ACL(Access Control List)和客户角色安全机制。同样提供加密的通信机制,比如TLS1.3;对于像基于UDP的CoAP协议使用DTLS。

其中的管理服务(Manager service)和反向代理(nginx)会进行安全机制的维护。管理服务通过JWT提供验证机制,并根据数据库中的权限列表提供授权服务。

nginx在Mainflux中提供几个重要的角色:

  • 反向代理
  • TLS终端
  • 负载均衡
  • 高可用(可伸缩性)
Authentication (AuthX)

管理服务(Manager service)提供系统实例的创建,同时管控着他们的权限。在实例创建的过程中,每一个用户和客户端(设备和应用)会分配一个JWT格式的token。
但是Mainflux的JWT机制在过期时间和TTL(time-to-live)上有些区别:1. 给应用的JWT是无状态的并且TTL很短;2.给设备的JWT是永不过期的;

通用的JWT需要是无状态的,没有回收机制。但是对于一些资源有限的设备刷新JWT的token有些困难,因为解码获取有效期所要求的算力可能并不满足;所以对于这类设备JWT是简单的不记名令牌,是一个密钥串并且预先烧录到firmware中,并且有必要的物理手段保护这个密钥串,比如防拆措施。
这种JWT的token的特点是无状态的并且是可回收的。

另外,除了JWT之外,服务器的公有证书也应该烧录设备的firmware中,主要用于创建TLS连接。

Authorization (AuthZ)

管理服务(Manager service)提供授权和鉴权服务。
授权服务,1.确认操作设备和应用的权限;2.行权,将设备或者应用分配到对应于同一个channel的通信组,没有权限的将不能操作这个channel的。

Building an End-to-End Example

Freeflex

系统名字

Hardware Sensor

ESP32 microprocessor

  • PIR (presence) sensor
  • Temperature and humidity sensor
  • Noise sensor (microphone)
  • Light sensor
  • Air quality sensor
  • NFC and RFID transceiver
连接到Mainflux

EACH DEVICE
协议: MQTT
消息格式: SenML
Channel:

  • 消息通道
  • 命令通道: 应用给设备下发命令
  • “bootstrap”通道: 设备管理和配置,共享于所有此类设备,用于获取初始化配置。
    量产及出厂步骤:
  1. 工厂使用同样的firmware烧写;
  2. 设备第一次接入Mainflux,通过“bootstrap”通道获取针对每个设备的初始化配置;
  3. Mainflux下发设备模型和channel名(消息通道和命令通道);
  4. Mainflux下发设备UUID、认证凭证、channel UUID,设备存到自己的flash中;
应用和监控台

后端:NodeJS+MQTT+MongoDB
前端:AngularJS
功能:系统管理+数据可视化

  • 设备列表
  • 连接列表
  • channel列表
  • 多样化的对传感器的可视化
  • 可视化的展示,直观的展示楼层的传感器安装位置及占用情况

LoRa Water Meter

Mainflux继承了一个LoRaWAN server,主要组成部分:网关、基站、LoRaWAN云服务。设备首先通过LoRa的物理协议连接到LoRa网关,LoRa网关通过UDP协议将信息转发到LoRaWAN云服务。

Hardware

MatchX LoRa gateway

Software

Mainflux集成了用Go语言写的LoRa Server,通过一个Adapter通过MQTT协议来连接Mainflux和LoRa Server,也就是说这个Adapter是一个MQTT客户端连着Mainflux和LoRa Server,主要工作是一个由LoRa Server到Mainflux SenML的转换。

开源物联网系统 java 开源物联网平台_HTTP_02

Summary

  • Apache-2.0 licensed
  • 微服务架构
  • 多协议支持(HTTP, MQTT, WebSocket, CoAP)
  • 设备管理和提供
  • 存储空间增长线性
  • 平台日志和仪表化支持
  • 容器部署

开源物联网系统 java 开源物联网平台_json_03

项目介绍及目录结构

架构设计

数据模型

微服务模型

微服务接口

== API by micro service:

  • UsersService
// RPC
service UsersService {
    rpc Identify(Token) returns (UserID) {}
}
//--------
// HTTP
type Service interface {
	Register(User) error
	Login(User) (string, error)
	Identify(string) (string, error)
}
  • ThingsService
type Thing struct {
	ID       string
	Owner    string
	Type     string
	Name     string
	Key      string
	Metadata string
}

type Channel struct {
	ID       string
	Owner    string
	Name     string
	Metadata string
}
// RPC
service ThingsService {
    rpc CanAccess(AccessReq) returns (ThingID) {}
    rpc Identify(Token) returns (ThingID) {}
}
//--------
// HTTP
type Service interface {
	AddThing(string, Thing) (Thing, error)
	UpdateThing(string, Thing) error
	ViewThing(string, string) (Thing, error)
	ListThings(string, uint64, uint64) (ThingsPage, error)
	ListThingsByChannel(string, string, uint64, uint64) (ThingsPage, error)
	RemoveThing(string, string) error

	CreateChannel(string, Channel) (Channel, error)
	UpdateChannel(string, Channel) error
	ViewChannel(string, string) (Channel, error)
	ListChannels(string, uint64, uint64) (ChannelsPage, error)
	ListChannelsByThing(string, string, uint64, uint64) (ChannelsPage, error)
	RemoveChannel(string, string) error

	Connect(string, string, string) error
	Disconnect(string, string, string) error

	CanAccess(string, string) (string, error)
	Identify(string) (string, error)
}

安装示例

参考文档

  • scalable-architecture-for-the-internet-of-things.pdf