物联网系统开发:从0到1构建IoT平台 第2版 付强 傅静涛
定 价:99 元
本书是一部从技术原理、工程实践、设计模式和最佳实践等多个维度详细讲解物联网系统和产品开发的著作。它涵盖物联网应用开发80%的场景,能指导读者零基础的读者从0到1构建一个功能齐备的物联网平台,并附有代码和解释。本书既有作者在物联网行业多年实操经验的总结,也结合了作者在高校的多年教学实践经验,是一本既适合高校学生、物联网初学者,也适合有经验的物联网开发者和架构师阅读的佳作。本书第1版是物联网系统开发领域的畅销书,几乎零差评。第2版新增了全面解析MQTT 5.0协议特性的内容,同时,为了适配EMQX最新版本,对书中的相关代码和配置均进行了更新。全书共14章,分为三大部分:第一部分(第1~2章)物联网基础介绍物联网基础知识,涵盖物联网的概念和常用协议。第二部分(第3~6章)MQTT协议详解与实战详细讲解MQTT协议,通过详尽的示例代码对物联网的核心协议MQTT协议的规范和特性进行讲解。内容包括MQTT 3.1.1和MQTT 5.0。第三部分(第7~14章)实战:从零开始搭建一个IoT平台物联网平台开发实战,讲解如何使用开源组件从0到1构建一个功能完备的物联网平台。
(1)作者背景权威:作者曾就职于趋势科技、诺基亚,现担任某物联网企业的CTO,在物联网领域有较大的影响力。(2)作者经验丰富:作者在物联网领域从业近15年,一直致力于物联网软硬件产品和平台的设计和开发,经验丰富。(3)畅销书全新升级:第1版是物联网领域的畅销书,累计印刷10余次,网店零差评,是读者公认的经典著作。(4)零基础可上手:可指导没有任务物联网技术基础的读者理解物联网的核心协议,并从0到1开发功能齐备的物联网平台。(5)注重实战:本书以实战为导向,手把手逐步教读者开发物联网平台,附案例代码,并给出了解释。
Preface 前 言为什么要写这本书2011年我在硅谷的时候,曾经参与设计和开发了一个物联网平台。这个平台的目的是为各种物联网设备提供统一的通信接口,以及提供数据存储和分析功能,降低物联网设备商的开发和运营成本。不过,由于物联网设备的异构性太强,同时平台的愿景过于超前,而当时物联网应用的发展包括资本的投入都远不及现在,这个项目不得不半路中止。2015年,我在国内和朋友联合创办了一家物联网相关的公司。为了支持公司的硬件产品,我们开发了一个提供统一通信和数据服务的物联网平台,不过吸取了之前的教训,这个平台只对同一组织(公司)里的多个产品提供支持。当时各大云服务商,比如阿里云,提供了非常成熟的物联网套件,我们将这些物联网套件中的一些功能移植到了自研的物联网平台上。这个平台从技术层面很好地支持了公司从0到1、从1到N持续盈利的全流程。在这个过程中我遇到过一些问题,也总结出一些非常有用的经验。在此期间,我也加入了一些物联网开发者的社区。在日常的技术交流里,我发现一些开发人员对常用的物联网协议的理解是有问题的,对一些功能应该在协议层面实现还是在业务层面实现不是很清楚。我曾在互联网上搜索过相关的技术文章,发现系统性讲解协议的规范和特性的文章非常少,不是只对一两个功能进行介绍,就是只翻译协议规范,缺乏代码示例。在这种情况下,我在GitChat的专栏写了我的第一篇文章《MQTT协议快速入门》,详细地讲解了物联网应用中最常见的MQTT协议的规范和特性,并对每一个特性附以丰富的代码示例。加入专栏文章的读者交流群后,我又发现读者还有很多关于设计、业务架构的疑问,深入理解MQTT协议并不能解决这些问题。这让我意识到,物联网应用开发并不像Web开发那样有成熟的设计模式和框架可以使用,开发者往往都是从协议级别开始往上搭,重复地造轮子。因此,我觉得有必要把我们在开发物联网平台中遇到的困难和总结的经验分享出来,从协议开始讲起,再覆盖物联网后台开发中常见的设计模式和最佳实践,让其他的物联网开发者少走一些弯路,少造一些轮子,进而更快速、更高效地上线自己的产品。读者对象物联网应用开发人员物联网架构师物联网平台开发人员对物联网感兴趣的开发人员有一定经验的IM平台、移动推送平台开发人员渴望学习更多物联网实际开发经验的人员如何阅读本书本书涵盖物联网应用开发80%的场景,理论和实战并重。本书内容分为三大部分。第一部分(第1~2章)为物联网基础知识介绍,涵盖物联网的概念和常用协议。第二部分(第3~6章)为MQTT协议详解,通过详尽的示例代码对MQTT 3.1.1和MQTT 5.0协议的规范和特性进行讲解。第三部分(第7~14章)为物联网平台开发实战,从零开始用开源的组件搭建一个名为Maque IotHub的物联网平台,在这个过程中讲解物联网后台开发中常见的设计模式和最佳实践。本书最后补充有结语与附录。结语总结了本书讲到的相关系统与知识体系,附录介绍了运行Maque IotHub的方法和步骤。如果你对MQTT协议已经非常了解,可以直接从第三部分开始看起,第二部分可作为协议规范参考指南。如果你是一名初学者,请务必从第1章的基础知识开始学习。勘误和支持由于作者的水平有限,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。书中大量的实例代码都可以从我的GitHub站点(https://github.com/suf?ish)下载。你也可以关注我在GitChat的专栏(https://gitbook.cn/gitchat/author/59ed8409991df70ecd5a0f8f),并加入专栏读者群进行交流。如果你有更多的宝贵意见,也欢迎发邮件到yfc@hz.cmpbook.com。期待能够得到你们的真挚反馈。致谢首先要感谢EMQX的开发者和贡献者,开发和维护一款强大的开源MQTT Broker非常不易。感谢GitChat提供平台并促成了本书的出版。感谢在写作过程中很多人的支持与帮助,他们是:赵华振、李斌锋、邓斌、戚祥、于伟、皮文星、陈育春、陆正武、虞晓东、张恒汝、高喆、刘威、刘冉、付志涛、宗杰、王大平、李振捷、李波、张鹏、管西京、闫芳、王玉芹、王秀明、杨振珂。 感谢公司的全体同人,大家的共同努力才给我提供了一个能够实践自己想法的机会。最后感谢关心我的家人,尤其是我的妻子和女儿,她们的支持是我完成本书的动力!谨以此书献给我最亲爱的家人,以及广大物联网开发者!
付 强
付强,资深物联网技术专家,有超过15年的物联网行业从业经验,现担任某物联网软硬件解决方案公司的创始人兼CTO。曾就职于趋势科技、诺基亚创新中心硅谷实验室,专注于物联网软硬件产品和平台的设计和开发。 CSDN专栏作者,撰写了多篇物联网和AI相关的专栏文章。傅静涛,工信部高级项目经理,在一流高校从事相关专业科研和教学近30年, 在物联网领域有非常深厚的积累。主持和实施了多个物联网软硬件产品和平台的研发与落地。
目 录 Contents前言第一部分 物联网基础第1章 什么是物联网 21.1 物联网和人工智能 31.2 物联网的现状与前景 4第2章 常见的物联网协议 62.1 MQTT协议 62.2 MQTT-SN协议 72.3 CoAP 82.4 LwM2M协议 92.5 HTTP 92.6 LoRaWAN协议 92.7 NB-IoT协议 102.8 本章小结 10第二部分 MQTT协议详解与实战第3章 MQTT协议基础 133.1 MQTT协议的通信模型 133.2 MQTT的不同版本 143.3 MQTT Client 143.4 MQTT Broker 163.5 MQTT协议数据包格式 173.6 本章小结 19第4章 MQTT 3.1.1协议详解 204.1 建立到Broker的连接 204.1.1 CONNECT数据包 204.1.2 CONNACK数据包 234.1.3 关闭连接 254.1.4 代码实践 264.2 订阅与发布 294.2.1 PUBLISH数据包 304.2.2 代码实践:发布消息 324.2.3 订阅一个主题 324.2.4 代码实践:订阅主题 354.2.5 取消订阅 374.3 QoS及其最佳实践 404.3.1 MQTT协议中的QoS等级 404.3.2 QoS0 404.3.3 QoS1 414.3.4 QoS2 424.3.5 代码实践:使用不同的QoS发布消息 454.3.6 实际的QoS 484.3.7 QoS的最佳实践 484.4 Retained消息和LWT 494.4.1 Retained消息 494.4.2 代码实践:发布和接收Retained消息 504.4.3 LWT 524.4.4 代码实践:监控Client连接状态 524.5 Keep Alive与连接保活 544.5.1 Keep Alive 544.5.2 代码实践 564.5.3 连接保活 574.6 本章小结 59第5章 MQTT 5.0协议详解 605.1 协议包内容扩展 605.1.1 属性集 605.1.2 原因码 605.2 更完善的连接管理 635.2.1 获取MQTT Broker的连接属性 635.2.2 代码实践:建立MQTT 5.0连接 655.2.3 Client主动断开连接 655.2.4 代码实践:主动断开连接,触发遗愿机制 665.2.5 Broker主动断开连接 675.2.6 代码实践:处理客户端标识符冲突 675.3 更完善的会话管理 685.3.1 清理会话启动 695.3.2 会话过期时间 695.3.3 代码实践:在CONNECT数据包中设定会话过期时间 705.3.4 代码实践:在DISCONNECT数据包中更新会话过期时间 705.4 新增消息过期机制 715.4.1 消息过期时间 715.4.2 代码实践:发布带有过期时间的消息 725.5 协议级别支持共享订阅 735.5.1 如何使用共享订阅 735.5.2 代码实践:使用共享订阅 745.5.3 代码实践:使用带通配符的共享订阅 755.5.4 代码实践:多个共享订阅组 765.6 数据包可携带用户属性 775.6.1 为什么要引入用户属性 775.6.2 典型的使用场景 785.7 可声明消息体格式 795.7.1 为什么要声明消息体格式 795.7.2 如何声明消息体格式 795.7.3 代码实践:发布带有消息体格式的消息 795.8 可设置主题别名 805.8.1 主题名映射 815.8.2 代码实践:使用主题别名 815.9 新增请求/响应模式 825.9.1 MQTT 5.0之前的解决方案 825.9.2 MQTT 5.0的解决方案 835.9.3 代码实践:使用请求/响应模式进行数据交互 845.10 订阅时可指定订阅标识符 855.10.1 订阅标识符 855.10.2 代码实践:使用订阅标识符 855.11 更完善的订阅选项 865.11.1 QoS等级选项 875.11.2 非本地选项 875.11.3 保留Retain标识符选项 875.11.4 保留消息处理选项 875.11.5 代码实践:设置非本地选项 875.11.6 代码实践:设置保留Retain标识符选项 885.11.7 代码实践:设置保留消息处理选项 895.12 更完善的认证机制 915.13 本章小结 92第6章 MQTT协议实战 936.1 AI IoT项目实战 936.1.1 用TensorFlow在Android系统上进行物体识别 936.1.2 如何在MQTT协议里传输大文件 946.1.3 消息去重 956.1.4 最终的消息数据格式 956.1.5 代码实践:上传识别结果 956.1.6 在浏览器中运行MQTT Client 976.1.7 代码实践:接收识别结果 976.1.8 搭建私有MQTT Broker 986.1.9 传输层安全 1006.2 MQTT常见问题解答 1016.3 开发物联网应用,学会MQTT协议就够了吗 1016.4 本章小结 103第三部分 实战:从零开始搭建 一个IoT平台第7章 准备工作台 1077.1 安装需要的组件 1077.2 Maque IotHub的组成部分 1087.3 项目结构 1097.3.1 IotHub Server 1097.3.2 IotHub DeviceSDK 1097.4 本章小结 111第8章 设备生命周期管理 1128.1 设备注册 1128.1.1 设备三元组 1128.1.2 EMQX的认证方式 1138.1.3 设备接入流程 1178.1.4 Server API:设备注册 1188.1.5 调整EMQX配置 1208.1.6 修改DeviceSDK 1218.1.7 Server API:设备信息查询 1228.1.8 Server API:获取接入IotHub的一次性密码(JWT) 1238.1.9 完善细节 1258.2 设备连接状态管理 1278.2.1 Poor mans Solution 1278.2.2 使用EMQX的解决方案 1288.2.3 管理设备的连接状态 1328.3 设备的禁用与删除 1368.3.1 禁用设备 1368.3.2 删除设备 1418.4 设备权限管理 1428.4.1 为什么要控制Publish和Subscribe权限 1428.4.2 EMQX的ACL功能 1428.4.3 集成EMQX的ACL功能 1468.5 给IotHub加一点扩展性 1488.5.1 EMQX的纵向扩展 1488.5.2 EMQX的横向扩展 1498.6 本章小结 151第9章 上行数据处理 1529.1 选择一个可扩展的方案 1529.1.1 完全基于MQTT协议的方案 1539.1.2 基于WebHook的方案 1549.1.3 数据格式 1559.1.4 主题名规划 1569.1.5 上行数据存储 1569.1.6 通知业务系统 1579.1.7 上行数据查询 1579.1.8 上行数据处理流程 1579.2 实现上行数据处理功能 1589.2.1 DeviceSDK的功能实现 1589.2.2 IotHub Server的功能实现 1609.2.3 代码联调 1629.2.4 通知业务系统 1649.2.5 Server API历史消息查询 1679.3 设备状态上报 1689.3.1 设备状态 1689.3.2 DeviceSDK的实现 1699.3.3 IotHub Server 的实现 1699.3.4 Server API:查询设备状态 1719.3.5 代码联调 1729.3.6 为何不用Retained消息 1729.4 时序数据库 1739.4.1 时序数据 1739.4.2 时序数据库概述 1749.4.3 收集设备连接状态变化的数据 1749.5 本章小结 177第10章 下行数据处理 17810.1 选择一个可扩展的方案 17910.1.1 完全基于 MQTT协议的方案 17910.1.2 基于EMQX RESTful API的方案 18010.1.3 下行数据格式 18010.1.4 主题名规划 18110.1.5 如何订阅主题 18210.1.6 设备端消息去重 18210.1.7 指令回复 18310.2 DeviceSDK端的实现 18310.2.1 消息去重 18310.2.2 提取元数据 18410.2.3 处理指令 18510.2.4 回复指令 18610.3 服务端的实现 18710.3.1 更新ACL 列表 18710.3.2 EMQX发布功能 18710.3.3 Server API:发送指令 18810.3.4 Broker自动订阅 18910.3.5 通知业务系统 19010.3.6 代码联调 19210.4 本章小结 195第11章 IotHub的高级功能 19611.1 RPC式调用 19611.1.1 主题规划 19711.1.2 等待指令回复 19811.1.3 服务端实现 19811.1.4 Server API:发送RPC指令 20011.1.5 更新设备ACL列表 20111.1.6 更新服务器订阅列表 20111.1.7 DeviceSDK端实现 20211.1.8 代码联调 20311.2 设备数据请求 20411.2.1 更新设备ACL列表 20511.2.2 服务端实现 20611.2.3 DeviceSDK端实现 20711.2.4 代码联调 20711.3 NTP服务 20911.3.1 IotHub 的 NTP 服务 20911.3.2 DeviceSDK端实现 21011.3.3 服务端实现 21111.3.4 代码联调 21211.4 设备分组 21211.4.1 功能设计 21311.4.2 服务端实现 21511.4.3 DeviceSDK端实现 21811.4.4 代码联调 22111.5 M2M设备间通信 22311.5.1 主题名规划 22311.5.2 服务端实现 22411.5.3 DeviceSDK端实现 22511.5.4 代码联调 22511.6 OTA升级 22711.6.1 功能设计 22711.6.2 服务端实现 22911.6.3 DeviceSDK端实现 23311.6.4 代码联调 23511.7 设备影子 23811.7.1 什么是设备影子 23811.7.2 设备影子的数据结构 23811.7.3 设备影子的数据流向 23911.7.4 服务端实现 24111.7.5 DeviceSDK端实现 24611.7.6 代码联调 24811.8 本章小结 250第12章 扩展EMQX Broker 25112.1 EMQX的插件系统 25112.1.1 Erlang语言 25212.1.2 安装编译工具 25212.2 我们会用到的Erlang特性 25312.2.1 Erlang简介 25312.2.2 变量和赋值 25412.2.3 特殊的 Erlang 数据类型 25512.2.4 模式匹配 25512.2.5 模块与函数 25612.2.6 宏定义 25712.2.7 OTP 25712.3 搭建开发和编译环境 25712.3.1 使用插件模板 25712.3.2 代码结构 25712.3.3 编译和打包 26012.4 实现基于RabbitMQ的Hook插件:emqx_rabbitmq?_?plugin 26012.4.1 插件配置文件 26012.4.2 建立RabbitMQ的连接池 26112.4.3 处理client.connected事件 26312.4.4 处理client.disconnected事件 26312.4.5 处理message.publish事件 26412.5 使用emqx_rabbitmq?_?plugin插件 26512.5.1 安装和启用插件 26512.5.2 测试插件 26612.5.3 管理插件配置 26712.5.4 集成emqx_rabbitmq?_?plugin插件 26812.5.5 IotHub 的全新架构 26912.6 本章小结 270第13章 集成CoAP 27113.1 CoAP简介 27113.1.1 CoAP的消息模型 27213.1.2 CoAP的请求/响应机制 27213.1.3 CoAP OBSERVE 27313.1.4 CoAP HTTP网关 27313.2 集成CoAP到IotHub 27413.2.1 EMQX的CoAP网关 27413.2.2 设备发起连接 27713.2.3 设备上报数据 27913.2.4 设备发送心跳 28013.2.5 设备主动断开连接 28113.3 本章小结 282第14章 使用其他语言扩展 EMQX 28314.1 EMQX的gRPC钩子 28314.2 gRPC简介 28414.3 基于EMQX的gRPC钩子实现插件功能 28414.3.1 ExHook的服务定义 28414.3.2 代码结构 28614.3.3 OnProviderLoaded接口 28714.3.4 OnClientConnected接口 28814.3.5 OnClientDisconnected接口 29014.3.6 OnMessagePublish接口 29014.4 启用emqx_rabbitmq?_node_plugin 29314.5 本章小结 294结语 我们学到了什么 295附录A 如何运行Maque IotHub 299