万物互联时代,很多人仍然会有这样一个疑问:“为何物联网概念与技术提出并发展了多年,却感觉离我们仍很遥远?”。解惑这个问题之前,我们不妨先探讨智能手机为何会成为人们生活不可或缺的一部分。智能手机可基于 Android 或 iOS 操作系统,承载运行多款 App,嫁接起技术与用户之间的桥梁。反观物联网之所以迟迟无法走进人们的生活,究其根本原因之一——应用的缺乏。在现如今这个软件吞噬硬件的趋势之下,作为一名开发者,该如何更为快捷简单的上手硬件应用开发?如何进行适合的工具选型?面对更为严峻的挑战,需要具备哪些新技能?
基于此,我们邀请了 Ruff CTO 郑晔和其他六位专家一起从物联整体架构、技术栈、应用开发平台到实战经验与安全方案进行「一天掌握物联网全栈开发之道」的技术分享,希望通过一天的时间,帮助开发者快速掌握物联网全栈开发之道。在此之前,我们特别采访了郑晔老师,请他从如何快速实现物联网应用的实战角度为我们答疑解惑。
个人从业经历和团队背景
在 IT 行业沉浸十几年,我的职业生涯分成三个阶段:
- 在东软,学会了做软件,而不仅仅是写程序,但对于制作软件的过程,我产生一个疑问,怎么做软件才是合理的。
- 在 ThoughtWorks,我学会了敏捷/精益软件开发方法,能用一个非常顺畅的过程制作软件。在那段经历的后期,我也开始思考,希望能够做一些能够对行业有影响力的事,Moco 就是我在那个阶段开始的一个作品。
- 在 Ruff,就是我现在所供职的公司,我希望用自己这些年对技术的理解,改变 IoT 应用开发的现状,打造一个 IoT 版本的 Android。
从个人的经历上来看,貌似跨度比较大,从软件到硬件,但本质上,我有一个核心关注点,提高开发者的效率。
- 通过软件过程,把事情做对,节省时间,比如对敏捷软件开发方法的推广;
- 打造工具,简化开发者的工作,比如 Moco;
- 编写框架,为开发者提供新的抽象,比如 Ruff。
在我心目中有一个偏执的印象,只有为程序员提供支持,无论是工具,还是基础库,才算得上高手,例如开发了 Linux 和 Git 的 Linus Torvalds、开发了 MapReduce 的 Jeff Dean 等技术大牛。
我们团队囊括了各方面的人才,有从 Intel、NVIDA 这样大公司出来的底层技术高手,也有一些为开源操作系统做过贡献的人,还有一些在云服务厂商工作的技术者等。
Ruff 的技术团队现在大约有30人左右的规模:
- 硬件团队,负责 Ruff 的开发套件,以及一些合作项目中,硬件的设计与生产;
- Ruff SDK 团队,负责硬件端 Ruff 的设计与维护;
- 云端团队,负责云平台的建设,甚至包括手机 App 的开发。
Ruff 设计宗旨及特点
Ruff 从始至终有一个理念:让 IoT 应用开发变得更简单。
Ruff 旨在让软件开发者能够进入到硬件开发的领域,因为软件开发者不懂硬件,Ruff 设计就是将底层的硬件概念隔离开,基于此,我们引入了设备抽象的概念,让开发者像用程序库一样操作硬件。
在我们看来,IoT 一定是未来重要的组成部分,但 IoT 发展得实在太慢,究其根源在于,能够在这个领域中开发应用的人太少,懂硬件的开发者稀缺,而懂硬件又懂应用的开发者更是少之又少。移动互联网领域已经为我们演示了如何为手机应用开发领域带来新的开发者,就是让软件开发者进入这个领域。对于属于未来的 IoT,我们希望看到同样的故事再次上演。
Ruff 现阶段解决的最重要的问题是,让软件开发者能够编写硬件应用,这等于为软件开发者打开一道新的大门。
与此同时,Ruff 还对研发效率非常关注。从入门开始,我们的开发者通常几分钟就能完成“Hello,world”级别的开发,而传统的方式中,开发者仅仅搭建环境这一项就需要很长时间。
再有,众所周知,测试驱动开发是更好的写代码方式,而这种方式的重点是小步快跑。在传统的硬件开发中,几乎是不可能的,主要是受下面几点所限:
- 传统硬件开发中,开发者必须把代码部署到硬件上,才能知道代码运行是否正常。
- 镜像烧写是一个比较漫长的过程,每次部署代码到硬件都需要很长时间。
所以,嵌入式开发者的习惯是,编写一段很长的代码,然后再部署到硬件上,慢慢调试,从研发效率的角度来说,这种做法效率极低。
在 Ruff 应用开发中,测试驱动开发是能做到的,因为 Ruff 有应用抽象,可以把硬件驱动和软件接口隔离开来,应用开发者只要保证软件接口正确的调用,硬件驱动开发者来保证驱动编写的正确性。这样,应用开发者只要保证应用逻辑的正确性即可,而 Ruff 提供了测试框架,让应用开发者可以在没有硬件的前提下,运行应用测试。应用在具体硬件上的测试,就成了集成测试,而不是开发者每步都要做的事情。
即便是硬件上的测试,因为 Ruff 分离了应用与系统,每次部署到硬件只要部署应用即可,系统无需重新部署,部署效率就大幅度提高了。
Ruff 物联网操作系统特点
侧重点的差异,现在各大公司出品的物联网操作系统大多是在原有的领域不断拓展,比如,华为的 LiteOS 是希望操作系统占用内存更少,ARM 的 mbed 希望让原来硬件工程师的工作稍微简单一点,所以,根本上来说,他们比拼的是存量市场,而 Ruff 要做的是增量市场,让软件工程师进入到硬件应用领域中来。
做增量市场的事情,谷歌是有经验的,因为他们做过 Android。但在 IoT 领域的探索,谷歌现在做得还不够,之前他们曾经做过 Brillo,后面变成了 Android Things,但他们没有解决的问题是一样的,这两个框架采用依然是硬件开发者的语言(比如:GPIO、I2C),软件开发者不会用,硬件开发者很难从 C 改成 C++或 Java。
基于 Javascript 开发硬件应用优势及难点
优势
首先,C/C++ 是硬件开发者相对熟悉的语言,但是,以基础设施的角度来看,C/C++ 有些老了,对于现代软件工程的支持存在天然的缺陷,比如,C/C++ 至今没有一个好的包管理工具。对于硬件开发人员来说,可移植性是个永远的痛,每次拿到一款新硬件,让程序跑起来都是件痛苦的事情。
对于其它非 C/C++ 的语言,要应用在硬件上,主要面临两个问题:
- 运行时,能不能把这个语言跑在硬件上,尤其是内存很小的单片机上,像 Java 这样的语言,就被排除了。
- 流行程度,有一些语言运行时很小,比如 Lua,但对大多数程序员而言,这些语言都是陌生的。
综合这些因素,在我们开始 Ruff 的时候,JavaScript 是当时看来最好的选择,社区蓬勃发展,各种配套工具很丰富,有各种运行时实现可供选择。随后的发展也可以看出,后来在其它公司在这方面的探索,也选择了 JavaScript 这条路。
难点
用 JavaScript 开发硬件,第一步就是让硬件能够运行 JavaScript。大多数开发者可能不理解这里的难度,很多人以为我们就是把 Node.js 移植到硬件上,其实不然。Node.js 能够运行 JavaScript 的基础是 V8,而 V8是一个为浏览器设计的 JS 引擎,在 PC 上运行时,它几乎可以完全不顾虑资源进行性能优化,所以,V8占用的资源非常多,而硬件领域,资源是受限的,V8引擎根本运行不起来,也就是 Node.js 根本不能在资源受限的硬件上运行。所幸,JavaScript 社区发展足够好,有很多 JS 可供选择。所以,我们前期的工作等于基于一个引擎构建了一个另一个 Node.js。
以 Ruff 的设计目标而言,有一个重点是,如何设计一个面向应用开发者的抽象,把硬件设计细节全部隐藏起来。直到我们找到了下面这段代码:
$('#led').turnOn();
很多第一次看到 Ruff 的软件开发者,尤其是 Web 开发者看到这段代码时,第一反应通常是这和 JQuery 很像。这就是我们想要的感觉,开发者面对的是他们有些熟悉的东西,而不是完全地陌生,心里负担会一下子降下来,有兴趣进一步了解。
Ruff 前期遇到的问题,大多是这种“表达”层面的难题,比如,怎么写驱动。对我们来说,把驱动实现出来并不难,难的是怎么表达成开发者们熟悉的模式。我们也参考了大量已有的框架,最终选定了现在的做法,从中不难看出 React.js 的影子:
driver({
attach: function(inputs) {
...
},
exports: {
turnOn: function() {
...
}
}
});
作为一个坚定的敏捷软件开发支持者,测试驱动开发(Test Driven Development)是我生命中不可或缺的一部分。在硬件开发中如何支持 TDD,因为 TDD 需要小步迭代,而传统的硬件开发中,每次都要把代码部署到硬件上,这个周期会非常长,很难实现 TDD。但基于我们的设计,我们有了一个很好的分层,就很容易把硬件操作变成软件方法调用,这样,我们就用软件习惯的方式进行测试,比如,使用 Mock Object 模式进行测试。
exports['test should call turn on while application is ready'] = function() {
runner.run(appPath, function() {
verify($('#led-r')).turnOn();
});
};
解决方案
更准确的说, IoT 全行业都缺乏足够的行业解决方案。因为物和网这两个概念长期处于独立发展的阶段,做硬件的人只关注硬件怎么运作得更高效,做业务的人难以跨越硬件鸿沟,很少有人把它们结合起来思考。任何希望构建行业解决方案的团队,都需要构建自己的软硬件团队,从行业的角度来说,这是极大的浪费。
我们现在也在探索一些行业解决方案,比如我们现在在工业物联网领域有一个设备运维的产品,能够让工厂的人时刻监控设备状态。站在业务的角度,这个方案并不复杂,但怎么把设备接入到云端,这就是一个鸿沟。有了 Ruff,整个过程就会变得相对容易很多,我们开发了一整套接入方案,现在我们就可以把软硬件作为一个整体进行思考,比如有了设备数据,可以怎样结合人工智能的方式,进行工艺上的改进,甚至客户可以怎样设计新的流程,适应基于 IoT 的生产模式。
单纯从建议上来说,很容易说从业务上进行整体思考,但从行业的现状上来说,缺少了一个让软硬件成为一体的基础,这也就是现在 Ruff 希望在行业里扮演的角色。
硬件应用开发平台安全性问题
安全是一个永远不可忽视的问题。在 Ruff 的设计过程中,我们也是非常关心安全问题的。相较于之前直接控制硬件,Ruff 的应用是运行在受控的(Managed)环境中。在这样的环境下,Ruff 就可以不断地提升运行时的安全性,应用在原封不动的情况下,整体安全性就会得到提升。Ruff SDK 提供的各种组件,比如 SSL,我们也会不断升级,保证能够反映当前行业比较新的进展。这就是应用平台一个重要的差异,应用不需要做什么,安全性就会得到提升。
在 Ruff 的设计中,我们还设计了一些机制,减少安全隐患,比如只允许一个应用,不存在像多应用破坏其它应用的可能性。在生产环境中也设计了一些机制,保证应用不会在陌生的条件下进行更新。随着 Ruff 在生产环境下的应用,我们会在这个领域投入更多的精力,为应用提供一个更加安全的运行环境。
软件开发者的硬件应用开发之路
硬件对于软件开发者来说,只是没做过,有学习门槛,因为需要懂硬件接口、驱动、中断处理、时序等技术,听完所需要的技术后部分开发者基本上就准备放弃了。
但如果换个角度来看,首先直接写一个程序,按个按钮点亮一盏灯,这样开发者几乎就可以很容易的开始起步硬件开发的学习。
$.ready(function (error) {
$('#button').on('push', function () {
$('#led').turnOn();
});
$('#button').on('release', function () {
$('#led').turnOff();
});
});
当学会控制硬件的之后,再去了解灯到底怎么点亮的,看类似这样的驱动代码,复杂度也就大幅度降低了:
turnOn: function() {
this.gpio.write(1);
}
从学习的角度,一个好的方式是在已有的基础上,逐渐扩展新知识。在硬件领域,之前没有特别好的入门方式,有了 Ruff,我们就可以一步一步地迈进硬件开发领域。
物联网面临的挑战及未来展望
硬件厂商做应用,是阻碍行业进步的一大痛点。
在很多硬件厂商眼中,不存在硬件和应用的区分,他们在做的事情,就是一个做硬件,如同当年手机厂商认为手机就是一个手机一样。今天的移动互联网已经告诉我们,手机只是一个计算平台,有了 Android 和 iOS 之后,上面可以承载多种不同的应用。大多数用过当年诺基亚和摩托罗拉应用的人,对比今天的手机应用,会非常明显的感受到,当年的应用使用体验有多糟糕。这和今天硬件厂商同时做硬件和应用是异曲同工。IoT 领域要发展,关键就是打破坚冰,实现社会分工:让硬件厂商做好硬件,让应用厂商做应用。
物联网领域目前的状态是,实现技术蓬勃发展,应用进展缓慢。
我们看到芯片厂商、硬件厂商、系统厂商不断地推陈出新,推进各种技术,硬件越来越强大,技术越来越先进,系统占用资源越来越少。但是,技术不能转换应用,这些越来越强大的技术怎么才能进入到人们的日常生活,这就是应用厂商要做的事情。
在我看来,物联网领域最大的挑战就是应用太少,这也就是我们现在在尝试解决的问题。没有足够多的人做应用,这个领域就不可能真正的发展起来。
关于物联网的未来,会不同的物联网应用,这里的应用不仅仅是在硬件上,而是作为一个完整的物联网应用,从硬件到云,甚至到手机的控制端。普通消费者可以获取各种应用,结合自己的硬件,实现各种物联网的场景。
我们之所以要构建 IoT 应用平台,主要是希望能够降低 IoT 应用的开发门槛,让更多开发者,尤其是软件开发者能够进入到 IoT 研发领域中。现在的 Ruff,为硬件端引入软件开发者,在我们的大 IoT 平台中,开发者可以在云端编写各种物联网应用场景,无需了解具体的设备是哪个厂商的。有了这样的平台,现在的软件开发者可以顺利进入物联网开发领域,构想各种有趣的场景。有了低的门槛,开发者便更容易进入,有了足够多的开发者,物联网也就未来可期了。