众所周知,tornado是一个非常好的非阻塞网络I/O框架,它能支持上万个连接,并支持长轮训,websocket。
The Internet of Things (IoT) is the network of physical objects or "things" embedded with electronics, software, sensors, and network connectivity.
我们想实现的目标是把iot device的功能抽象出来,用API的方式呈现给开发者。
中间的问号部分就是我们想实现的IOT服务器,它能够与device进行通信,并且把device的功能用API的形式展现给开发者,同时它也可以响应开发者的API调用,获取Device数据或者让Device执行某种动作。
IOT Device设备,我们选择了ESP8266,它具有wifi连接,并且支持TCP/IP。并且可以驱动其他的开源hardware模块(如Arduino module).
通过Tornado的tornado.tcpserver
类,我们保持服务器和Device之间的TCP连接,并保持心跳检测。
通过Tornado的tornado.web
类,我们提供主要RESTful API给到开发者。
我们需要管理用户和它们名下的Device,实际上我们给每个用户和device加上了独一无二的token。同时引入了SQLite,把User token和Device token关联起来。我们用token实现权限控制。用户可以通过API查询属于自己的Device。
理想情况下,我们把device的功能抽象成一个个HTTP methods GET and POST. 这也是IOT server的核心功能。比如Device驱动了一个温度传感器,此时我们应该抽象出一个API:GET temperature. 用户通过这条API即可以得到当前温度。这并不容易做到, 但我们尽可能把它简化了。我们这里定义了一些规则,比如Read,Write函数。像Seeed的Grove module,只需要稍微修改一下原来的Arduino代码即可以抽象出它们的API。
一个好的sever应该实现事件处理,它类似一个紧急通知或者是一个实时信息,能让实时通知应用层。我们在服务器实现了event队列,它会对每一个event排队并逐个发送给应用层。我们用websocket来实现这一过程。通过Tornado的tornado.websocket
类我们很快做好了服务器端的websocket功能。应用层只需要简单实现websocket调用,即可以实时拿到device的event事件。
除了上述功能外,服务器还实现了一种云端固件编译的方法,用户通过API的方式定义编译哪些module的驱动进入固件,服务器会调用相关的编译链依据配置编译。然后通知device云端下载固件。这需要固件支持OTA升级功能。 这里我们利用了Tornado的长轮训(long-polling)机制来做编译和OTA状态更新。因为编译和下载固件的时间较长,用普通的HTTP请求会造成超时。
我们在TCP通信种采用了AES加密,我们自己实现了这种加密方式。 并且API调用采用了https加密,Tornado很容易实现https方式, 例如:
# implementation for SSL
http_server = tornado.httpserver.HTTPServer(application)
TCPServer(ssl_options={
"certfile": os.path.join("/var/pyTest/keys/", "ca.csr"),
"keyfile": os.path.join("/var/pyTest/keys/", "ca.key"),
})
不过我们直接使用nginx做https加密,效果是一样的。
所有的API请求返回数据格式使用json.它易于使用和理解。 例如:
{
"status": 200,
"msg": "OK"
}
我们完成了这个轻量级服务器,它是完全开源的。 Github地址:https://github.com/Seeed-Studio/Wio_Link
我们在这个服务器基础上做了一些额外事情:
- 我们实现了20+ Grove Sensor 的web API
- 我们实现了基于这个服务器的IFTTT channel.