小编说:DevOps 领域在近年来变得流行而普遍。它强调不同的角色之间共同协作,以及如何工作得更加紧密,就像这个词语的词根暗示的那样——开发和运维。但是DevOps和物联网有什么关系? 本文选自《DevOps实践》,将与您探讨DevOps和物联网的关系以及与您动手制作一个简单的物联网设备。
- DevOps和物联网有什么关系?
迄今为止,我们讨论的物联网的基础,基本上是寻常的互联网加上我们无法想象的节点数。我们也看到,在未来的几年中,能以各种形式联网的设备数量将继续呈指数增长。这一增长将是因特网的机器对机器部分。
但是,对于更加关注快速交付的DevOps,真的适合关键嵌入式设备的大型网络吗?
经典的反例是DevOps在核设施或者在诸如心脏起搏器的医疗器械中。但是单纯地更快发布不是DevOps的核心理念。它是通过将不同学科的人紧密联系在一起工作,更快、更准确地发布。
这意味着让类产品环境的测试环境贴近开发者,同时大家的合作更加紧密。
这么说的话,看起来DevOps可以用在保守的传统行业。
当然,不能低估面临的挑战:
···嵌入式设备的生命周期比传统的客户端——服务器计算机要长。消费者不能期望在每个产品周期都升级。同样,工业设备部署的地方更换起来可能很昂贵。
···相比桌面计算机,物联网设备失败的模式更多。这让测试变得更加困难。
···在工业部门和企业部门,可追溯性和可审计性是很重要的。这和在服务器上部署是一样的,但物联网端点比服务器更多。
···传统的DevOps可以将很小的变更部署到用户的一个子集。如果修改不工作,我们可以修复并重新部署。如果对我们一个已知的用户群来说网页渲染很糟糕,并且这个问题可以快速修复,潜在的风险就很小。另一方面,如果一个单的物联网设备控制的物体,例如一道门或一个工业机器人出现故障时,造成的后果可能是灾难性的。
物联网领域对于DevOps来说挑战很大,但是换种方式不见得会更好。DevOps也是一个工具箱,你需要思考从中找挑出的工具是否能正确应对当前工作。
我们仍然可以使用许多DevOps工具箱中的工具,只需要确保我们在做正确的事情,而不只是在不理解问题的前提下实现想法。
下面是一些建议:
···只要你在测试实验室中,失败和快速周转是可以的。
···确保你的测试实验室和产品环境接近。
···在实验室不要只使用最新版本,也要兼容旧版本。
- DevOps的物联网设备动手实验室
为了得到动手环节的灵感,让我们来制作一个简单的物联网设备,它可以连接到Jenkins服务器并且显示出构建的状态。通过这种方式,将我们尝试的物联网设备和DevOps结合起来!
在构建失败的情况下,将闪烁的LED作为状态显示。这个项目很简单,但是聪明的读者可以以此为基础扩展项目。为本次练习挑选的物联网设备比较灵活,可以实现比LED闪烁更多的功能。
该项目将有助于说明一些可能性以及物联网的挑战。
NodeMCU Amica是来自Espressif的基于ESP8266芯片的可编程的小设备。除了基本的ESP8266芯片,Amica板额外的特性让开发更加容易。
下面是一些设计的规格:
···Tensilica Xtensa LX106是一个32位的RISC CPU,运行频率为80MHz。
···它的Wi-Fi芯片允许它连接到我们的网络和Jenkins服务器。
···NodeMCU Amica板有一个USB接口可以给固件编程并连接到电源适配器。ESP8266芯片需要一个USB到串口的适配器去连接USB接口,它由NodeMCU板提供。
···板子有几个输入/输出的端口,可以连接到某些硬件上来可视化构建的状态。开始我们会做得比较简单,只使用连接到设备上某个端口的板载的LED。
···NodeMCU自带的固件可以通过Lua语言来编程。Lua是一种高级语言,可以快速实现原型。顺便提一句,它在游戏编程领域也很流行,也可以从另一方面说明Lua的高效。
···考虑到它提供的这么多功能,这个设备相当便宜:
很多地方都可以买到NodeMCU Amica,从电子商店到网上经销商。
买到NodeMCU不难,从硬件的角度来说项目也很简单,在实践中也可以采用Arduino或者树莓派,如果它们更容易获得。
下面是一些NodeMCU的入门提示:
···NodeMCU包含的固件提供了交互式Lua解释器,可以通过串行端口访问。你通过串行线来直接开发代码。在你的开发机上安装串行通信软件。这样的软件有很多,比如在Linux下的Minicom和Windows下的Putty。
···使用串口设置9600波特率、八位、无奇偶校验和一个停止位。这个设置通常缩写为9600 8N1。
···既然我们已经有了串行终端连接,将NodeMCU连到USB端口,切换到终端,验证你在终端的窗口看到了提示符。
如果你使用的是Minicom,提示的窗口如下:
开始写代码前,根据具体的NodeMCU的出厂设置,你可能需要往设备烧录固件的镜像。如果在前一步你看到了提示符,就不需要烧录固件的镜像。如果以后你需要在镜像中加更多的特性就得重新烧录镜像。
下面是一个用wget命令下载固件的例子。发布的版本号用整数和浮点数表示,根据你的需要去选择具体的版本。对于嵌入式的应用来说,整数的固件版本通常就足够用了:
代码语言:javascript复制wget https://github.com/nodemcu/nodemcu-firmware/releases/
download/0.9.6-dev_20150704/nodemcu_integer_0.9.6-dev_20150704.bin
你也可以在开发机器上通过GitHub源码直接构建固件镜像,或者也可以根据你的规格使用在线构建服务区构建一个固件。
在线构建的服务地址是http://nodemcu-build.com/。值得一看。如果不出意外,构建统计图颇为耐人寻味。
既然已经有了一个合适的固件文件,你需要安装固件烧录工具,才能把固件镜像文件上传到NodeMCU:
代码语言:javascript复制git clone https://github.com/themadinventor/esptool.git
按照代码库中的README安装指南文件来安装。
如果不喜欢README中建议的系统安装,你可以根据你的系统发行版去安装pyserial的依赖并在git克隆的目录中运行这个工具。
下面是安装pyserial依赖的命令例子:
代码语言:javascript复制sudo dnf install pyserial
实际的固件上传需要一些时间完成,但是进度条的显示可以让你知道发生了什么。
下面的例子是在本书撰写时,在命令行中上传0.9.6固件的命令:
代码语言:javascript复制sudo python ./esptool.py --port /dev/ttyUSB0 write_flash 0x00000 nodemcu_
integer_0.9.6-dev_20150704.bin
如果在连接NodeMCU时串行命令行出现乱码,你可能需要为烧录固件的命令提供一些额外的参数:
代码语言:javascript复制sudo esptool.py --port=/dev/ttyUSB0 write_flash 0x0 nodemcu_
integer_0.9.6-dev_20150704.bin -fs 32m -fm dio -ff 40m
命令esptool也有其他的功能,可以用来验证设置:
代码语言:javascript复制sudo ./esptool.py read_mac
Connecting...
MAC: 18:fe:34:00:d7:21sudo ./esptool.py flash_id
Connecting...
Manufacturer: e0
Device: 4016
固件上传完成后,重置NodeMCU。 这个时候你应该已经有了一个带有NodeMCU欢迎提示的串行终端。通过使用工厂提供的NodeMCU固件或者上传一个新的固件到设备都可以达到这个状态。 现在,我们开始试试一些“hello world”风格的练习。 一开始,只要我们连接到NodeMCU Amica板GPIO引脚0上,LED就开始闪烁。如果你有其他类型的板子,你需要找出它是否有LED,如果有,输入/输出引脚是哪根。你也可以自己包装一个LED。
如果终端软件允许,你可以将程序作为文件上传到NodeMCU,或者直接在终端上敲击代码。
你可以首先试着点亮LED:
代码语言:javascript复制gpio.write(0, gpio.LOW) -- turn led on
然后用下面的命令关闭LED:
代码语言:javascript复制gpio.write(0, gpio.HIGH) -- turn led off
现在,你可以循环下面的语句,其中穿插一些延迟语句:
代码语言:javascript复制while 1 do -- loop forever
gpio.write(0, gpio.HIGH) -- turn led off
tmr.delay(1000000) -- wait one second
gpio.write(0, gpio.LOW) -- turn led on
tmr.delay(1000000) -- wait one second
end
此时,你应该能够验证一个基本工作的设置。直接在终端输入代码有点原始。 NodeMCU有不同的开发环境来提高开发的体验。
在能够完成实验前,我们需要一些额外的提示。使用以下命令连接到无线网络:
代码语言:javascript复制wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
SSID和password需要用网络真实的SSID和密码替换掉。
如果NodeMCU正确连接你的无线网络,这个命令会打印出从网络的dhcpd服务器获得的IP地址:
代码语言:javascript复制print(wifi.sta.getip())
这段代码会连接到www.nodemcu.com的HTTP服务器并且打印返回码
代码语言:javascript复制conn=net.createConnection(net.TCP, false)
conn:on("receive", function(conn, pl) print(pl) end)
conn:connect(80,"121.41.33.127")
conn:send("GET / HTTP/1.1rnHost: www.nodemcu.comrn"
.."Connection: keep-alivernAccept: */*rnrn")
你可能还需要计时功能。下面的代码每隔1000毫秒打印hello
代码语言:javascript复制world:
tmr.alarm(1, 1000, 1, function()
print("hello world")
end )
在这里,我们声明了一个匿名函数并将其作为参数发送给timer函数,不经意地显露出了Lua的函数型范式。匿名函数每隔1000毫秒,也就是1秒被调用一次。
要停止timer,只需要执行:
代码语言:javascript复制tmr.stop(1)
现在,你应该明白了所有可以自行完成实验的细节。