## 使用 Python 进行物联网端到端原型开发 文/刘凯 ### Python 语言的传统优势与发展 凭借简单的语法、丰富的标准库和第三方库,以及与主要的编程语言的对接能力,Python 覆盖了大多数计算领域,成为一门通用计算编程语言。Python 的传统应用领域如:服务器后端、网络爬虫、服务器运维自动化、安全渗透等。这主要是 Web 相关领域,物联网需要在 Web 基础上增加设备域与数据域设计。 设备域中,长久以来一直被忽视的嵌入式系统,最近也出现了若干迭代速度惊人的 Python 项目。这包括历史悠久的 PyMite 及其衍生品种 Pymbed,开源的MicroPython ,以及采用商用许可证的 Zerynth。在嵌入式 Linux 中,Python 是必备的硬件编程语言之一。 数据域中,Python 凭借着在数据分析领域的长期积累以及对接 Java 的能力,在统计分析、科学分析、大数据分析、数据可视化以及人工智能领域也有长足发展。 随着 Python 在嵌入式系统与大数据分析两个领域日渐流行,Python 开始更多地出现在国外高校入门编程教材中。与此同时,Python 与其他动态语言一样,利用 JIT 编译器和 libuv 等异步 I/O 库实现了运行速度的大幅度提升。现在 Python 不仅开发迭代速度快,而且运行速度上也不输其他语言。 ### 快速搭建物联网原型 本文将演示如何使用 Python 和一些关键软硬件来快速搭建一个农业物联网的验证原型。物联网的碎片化趋势在农业也非常明显,农业可以细分为田、林、牧、渔几个子行业,其网络覆盖范围、数据采集、设备构成都存在很大差异。作为一个典型的农业物联网系统,其构成应该包括: 1. 传感器:如温度、湿度、二氧化碳、含氧量、酸碱度、水位传感器等; 2. 执行器:如水泵、卷帘门、继电器等; 3. 节点设备:联接传感器与执行器,并通过无线传感器网络保持与网关的通讯; 4. 网关:将无线传感器网络报文通过 TCP/IP 转发给云计算应用; 5. 云端应用:负责联接网关,并通过 Web 为用户和第三方应用提供设备与业务管理接口; 6. 客户端:通过浏览器、手机 App 实现现场管理。 ### 组网技术 不仅仅是农业,任何物联网系统选型过程中一个很重要的问题就是组网技术的选择。物联网组网与联网考虑的因素很多,包括: 1. 通讯技术:速率、距离、功耗、带宽、调制技术等; 2. 逻辑层级:标准的 TCP/IP 通讯包括物理层、媒体访问层、数据链路层、网络传输层; 3. 商业生态:各类标准的替代性、普及率等。 技术决策者必须了解很多系统知识,否则很容易做出错误的决定。作者可以给出一些经验: 1. 覆盖范围:离散性物联网如共享单车必须依靠蜂窝数据技术,如 GSM/NB-IoT;可集中管理的,或附近没有公众移动网络基站的地点,如工业、农业、小区可以考虑走非运营商的无线网络,包括 Mesh、LoRa、WiFi 等; 2. 移动能力:高速移动会形成多普勒频移效应,机动性要求较高的物联网系统必须使用宽带调制技术,例如 eMTC/LTE,而非 NB-IOT; 3. 数据速率:要实现高速且覆盖范围广必须选择 LTE/eMTC,代价是极高的功耗。 普通物联网应用大多要求低功耗、低占空比,LoRa 和 Sigfox 是低功耗广域网络(LPWA)的典型,功耗低、但是通信速率也较低。 与此相对应的是短距离无线网络(SR-WPAN),低功耗、中等速率,但是牺牲通讯距离,必须使用 Mesh 以及较为复杂的 MAC 协议和无线调度算法,同时中继节点的功耗也不低。短距离无线网络在 ToF 定位精度和网络定位上占据优势,典型案例是 iBeacon。 1. 工作环境:2.4GHz 的无线电衰减特性远比 Sub-1GHz 要差,同等功率在雨天通讯距离锐减,所以户外物联网优先考虑 Sub-1GHz 无线技术; 2. 法律法规:蜂窝数据属于授权频段,ISM 属于非授权频段,各国的划分不同,且有不同的发射功率和占空比要求,所以这方面因素也需要考虑在内; 3. 网络堆栈:蜂窝数据、WiFi、BLE、6LowPAN 属于已经构建完整堆栈的技术,而其他各类技术或多或少都有互操作性问题。虽然 Thread/IPv6 成为近期热点,但是实际工程中是否能够充分利用还是一个疑问。 正是因为这些因素的彼此制约,所以没有一种连接技术可以满足所有需求,决策者必须根据自己的系统特点进行选择。 回到我们的案例中,农业物联网的共性是数据传输率低、传输距离较远,LoRa 的调制技术很好地满足这两项要求,回避了复杂的 Mesh 网络。由于 LoRaWAN 来自于 LoRaMAC,其 MAC 层是针对低功耗数据采集优化的,上传采用 Aloha 竞争方式,而下传采用时分调度方式以降低功耗。因为农业传感器对于低功耗要求不敏感,作者将其简化为上传和下传均采用 Aloha 竞争方式,在低占空比情况下,可以满足农业物联网需求。 传输模块使用自己研发的 SX1272/1278 LoRa MODEM,支持 433/470/868/915MHz。MODEM 内置 STM32 采用 ARM mbed C++ 开发,支持多种堆栈固件,并通过 UART/USB 接口提供 AT MODEM 接口。以模块、U 盘、MiniPCIe 网卡形式提供,可以适配各种深嵌入式系统以及嵌入式 Linux。 ### 节点设备 由于农业生产领域的价格远不如消费电子领域那么敏感,该案例使用 STM32F401,加载 MicroPython 进行节点设备的固件开发,STM32F401 主控 MCU 与 LoRa 模块采用 UART 通讯,并通过 AT 指令集进行通讯。 MicroPython 是2015年起特别流行的一种嵌入式 Linux,该版本将桌面 Python 的许多编程体验直接带入了 MCU 级别的嵌入式系统。 与 C/C++ 相比,Python 是一种更加抽象的语言。Python 丰富的数据类型可以大大简化算法的开发,减少开发者实现数据流、编码和浮点数的麻烦;匿名函数可以对应中断服务程序实现事件驱动开发模式;生成器和 yield 减少了开发者对于任务调度的担心,并可以减少堵塞型 delay 函数的使用。 Python 最初的应用目的是脚本,所以可以支持面向过程、面向对象和函数式编程。对于长期使用 C/C++ 语言开发嵌入式应用的开发者而言,MicroPython 可以全方面地改善开发环境,降低开发工作量,加快迭代速度。同时开发者可以在 Python 中不断摸索这几种编程范式,学习提高。 利用 MicroPython ,可以快速构建节点设备原型。节点设备固件可以参考开源工程 LoPy,该项目整合了 LoRa 与 MicroPython ,所以其应用代码经过修改后可用于本案例中。由于需要集中供电的原因,大多数农业物联网节电设备是安装在太阳能电池板和蓄电池附近的,所以还可以通过有线连接方式,如 RS232/RS485/CAN/LIN 来访问附近的不具备无线传输能力的传统设备、传感器、执行器和电源子系统。 1. 安装 arm-none-eabi-gcc 交叉编译器,推荐使用 Linux 操作系统; 2. 从 GitHub 中复制 MicroPython 工程; 3. 选择 STM32F401 或 STM32F405 为目标进行交叉编译; 4. 使用 st-flash/openOCD 工具将 MicroPython 固件下载到目标 MCU 中去; 5. 通过 USB 连接目标板与 PC,安装 CDC/MSD 驱动; 6. 通过 TeraTerm 终端软件连接目标板,进入 REPL 命令行,开发用户脚本; 7. 开发者可以在 REPL 中通过 print 语句和抛出异常来定位错误,调试程序; 8. 调试完毕后,将用户脚本复制到 STM32F401 闪存内置文件系统中; 9. 在 REPL 中软复位运行用户脚本; 10. 必须弹出 MSD 后安全退出操作系统; 11. 上电复位脱机运行用户脚本。 ### 网关平台 本案例中采用 LoRa+Linux+CPython+panStamp 模块构成网关设备。 网关设备可以选用具备 WiFi/4G 通讯能力的 Linux 单板机,在能够保证三防和稳定电源的前提下,树莓派、工控机均可以使用。不同Linux发行版对于 Python 支持是不一样的,但是总能够找到一种方式把 Python 安装到嵌入式 Linux 中去: 1. 最原始的交叉编译 Linux(CLFS)中,可以交叉编译CPython 或 MicroPython UNIX 版; 2. OpenEmbbed 构建的预编译 Linux 发行版或 OpenWRT 嵌入式 Linux,可以直接安装CPython ; 3. 完整版 Linux 中,已经原装了 CPython /PyPy/Jython 等不同的实现。 树莓派的 Raspian 操作系统是完整的 Debian 发行版 ARM 分支,至少有两种成熟框架可选: 1. panStamp 开源物联网网关,使用 LoRa 堆栈替换其 FSK 传输模块和堆栈; 2. OpenHab 开源智能物联网网关,采用 Java OSGi,可以通过 jython 设计 LoRa 插件对接 OSGi 框架。 panStamp 是西班牙工程师 Luis 的开源工程,面向智能农业,后拓展到工业自动化、物流和智能楼宇场合。该功能使用 TI CC430 系列串口射频模块和树莓派,实现了一个完整的开源物联网网关:射频 MAC 堆栈、网页管理界面、异步消息队列、数据持久、数据缓存、集群管理、事件处理规则、云端服务器联网等等,堪称物联网网关的典范设计。实际上由于其内置事件处理规则,也可以将其视为边缘处理器了。开发者可以直接复用 panStamp 的工程,下载源码复制到指定路径中。但是许多情况下开发者依然需要做些适配,主要的工作量是: 1. 升级多语种资源包,支持中文; 2. 升级射频模块与堆栈更换; 3. 升级网页管理界面,支持响应性 UI 设计; 4. 升级为工业级 Linux 单板机,以适应恶劣的户外环境; 5. 云服务适配,支持国内供应商。 ### 服务器后端 在此例中,农业物联网传感器网络可以独立自成体系,借助移动终端和 WiFi 网络也可以访问到网关的管理界面,实现简单管理和封闭式生产系统。但是要构建一个完整的物联网系统平台,并与农业的其他应用如农资监控和调度、环境检测、质量管理、产品安全、物流管理与农业品加工业等进行整合,需要将此例中的农业生产物联网系统联接到云端应用,并通过 REST API 将系统抽象化后为其他系统提供服务,同时也从其他系统中获得必要信息服务。 作者对于物联网的设计总体思路是: 1. 将设备接入与应用迭代拆分成两个独立的子系统,采用消息队列 /REST API 连接; 2. 采用较大生态的 Web 框架实现业务扩展与功能扩展; 3. 根据数据流量和实时查询要求,采用缓存、关系数据库和时序数据库实现物联网数据的梯度存储; 4. 采用响应式前端以适应各类浏览器以及混合 App 的 UI 需求。 ### 标准化联网协议 此案例中,panStamp 与云端采用 MQTT 方式联网。MQTT 协议是最常见的物联网协议之一,并支持 TLS,已经成为各大云计算供应商的标准配置。树莓派和其他 Linux 单板机资源足够,可以使用 MQTT over TLS。 除了 MQTT 之外,还有 CoAP/HTTP 等联网方式,此外还存在大量的物联网系统采用私有和行业协议。从开发角度来看,Python 的 Twisted/Tornado 都可以轻松胜任此类设计任务。一个设计不完善的私有协议很大概率可能是系统失败的开端,并引发团队内部设备端与服务器端互相推诿,造成项目拖延。 ### Web 开发 由于 MQTT 解决了数据传输以及数据分享两个重要环节,甚至可以直接使用手机 APP 接入 MQTT 实现无后台的简单应用。但一般来说,需要 Web 服务器来实现一些基础服务,比如界面、RBAC/ACL、REST API、运维管理和数据分析等。如果使用 Python 来开发 Web 服务器,可以推荐 Flask。 Flask 是一种微型 Python Web 框架,基于 Werkzeug WSGI 工具包和 Jinja2 模板,扩展相对容易。上述的基础服务都有对应扩展可供选择,同时支持服务器的热更新。此外,可以通过 gevent/Gunicorn 实现性能提升。 ### 数据库 数据库在物联网的作用因系统而异。在此例中,农业物联网的数据采集速率较慢,温度、PH 值、风速等气象因素以及农作物的生产环境要素变化都很慢,而且农业传感器的数量也不多,因此可以将其保存在传统关系数据库,或文档型数据库中。其他中高速数据采集系统中,如何协调数据规模和查询实时响应性能是需要考虑的重要问题。例如心脏监护仪采样率是 1Ksps,24小时总数据量约为 82M(8640万)采样点,如果同时接入10万台监护仪,每24小时就会增加巨量数据,突破普通关系数据库的限制,造成慢 SQL 查询。而 DBA 能够做的各种分片技术在快速增加的数据面前都只是治标不治本。 所以小规模慢速物联网可以忽略的数据库问题,在大规模的中高速物联网应用中将成为性能瓶颈,需要根据数据流量和实时查询要求,采用缓存、关系数据库和时序数据库实现物联网数据的梯度存储。 在数据缓存中最常见的是 redis。它可以将采集物理量如温度、采用时间戳标识,并设置超时自动删除。例如:node0001-temp-2017052411102200,设置5秒后删除,那么在 redis 内存数据库只保存5秒内的数据点。规模可控,且可以高速分发给需要的应用,比如网页前端或第三方网站。 Python 脚本可以采用 redis-api 对接 redis 数据库。 时序数据库是专为大规模时序信号采集(带时间戳)而设计的数据库。目前有十几种基于 MongoDB/Cassandra 的数据库,由于这些数据库的接口大多都有对应的包如 pymongo、pycassa/pycassandra,可以很方便地对接这些数据库。百度提供的天工时序数据库也是可以使用的,采用其提供的 Python 客户端即可以访问。 使用这些接口软件包需要注意是采用同步还是者异步模式编写的软件包,并对接到所使用的网络或 Web 编程框架中。 以上是作者总结的一些物联网的共性,图1为一个可扩展的物联网架构。 图1  EPIC (Expandable  Python  IoT Cloud) 架构 图1 EPIC (Expandable Python IoT Cloud) 架构 ### 总结 本文以农业物联网为例,介绍典型的物联网端到端的快速原型构建方法,这其中 Python 作为一种面向系统集成的“胶水语言”,在物联网端到端链条中扮演了一个跨界开发的角色。除了原型开发, Python 作为一种通用语言,还可以多方面地加速物联网的开发,从包括芯片原型、SPICE 仿真、系统原型、设备域终端的硬件与固件、组网堆栈与仿真、联网协议、网关设备的硬件与软件、服务器的前后端软件与架构、数据分析的持久层设计与数据分析平台、用户端的 App 软件,以及开发辅助工具箱等。