AWS IoT

平台架构

image

AWS服务

image

  • Amazon DynamoDB—托管NoSQL数据库
  • Amazon Kinesis—大规模流式数据实时处理
  • AWS Lambda—EC2云虚拟机运行代码响应事件
  • Amazon Simple Storage Service(S3)—可扩展云存储
  • Amazon Simple Notification—推送通知服务
  • Amazon Simple Queue Service—消息队列服务

SDK

image

  • AWS IoT 设备 SDK 使用 MQTT、HTTP 或 WebSockets 协议将硬件设备连接到 AWS IoT,硬件设备无缝安全地与 AWS IoT 提供的设备网关和设备影子协作。
  • 设备 SDK 支持 C、JavaScript 、Arduino、Java和Python。
  • 设备 SDK 包含开源库、带有示例的开发人员指南和移植指南,用户根据硬件平台构建 IoT 产品或解决方案。

设备网关

image

  • AWS IoT 设备网关支持设备安全高效地与 AWS IoT 进行通信。设备网关可以使用发布/订阅模式交换消息,从而支持一对一和一对多的通信。凭借此一对多的通信模式,AWS IoT 将支持互连设备向多名给定主题的订阅者广播数据。
  • 设备网关支持 MQTT、WebSocket 和 HTTP 1.1 协议,也支持私有协议。
  • 设备网关可自动扩展,以支持 10 亿多台设备,而无需预配置基础设施。

认证和授权

image

  • AWS IoT 在所有连接点处提供相互身份验证和加密。AWS IoT 支持 AWS 身份验证方法(称为"SigV4")以及基于身份验证的 X.509 证书。使用 HTTP 的连接可以使用任一方法,使用 MQTT 的连接可以使用基于证书的身份验证,使用 WebSockets 的连接可以使用 SigV4。
  • 使用 AWS IoT 生成的证书以及由首选证书颁发机构 (CA) 签署的证书,将所选的角色和/或策略映射到每个证书,以便授予设备或应用程序访问权限,或撤消访问权限。
  • 通过控制台或使用 API 创建、部署并管理设备的证书和策略。这些设备证书可以预配置、激活和与使用 AWS IAM 配置的相关策略关联。
  • AWS IoT 还支持用户移动应用使用 Amazon Cognito 进行连接,Amazon Cognito 将负责执行必要的操作来为应用用户创建唯一标识符并获取临时的、权限受限的 AWS 凭证

注册表

  • 注册表将创建设备标识并跟踪元数据,如设备的属性和功能。
  • 注册表向格式一致的每台设备分配唯一的标识,而不管设备的类型和连接方式为何。此外,它还支持描述设备功能的元数据,例如传感器是否报告温度,以及数据是华氏度还是摄氏度。
  • 注册表存储有关设备的元数据,无需支付额外费用;并且需要每隔 7 天至少访问或更新注册表条目一次,注册表中的元数据就不会过期。

以JSON格式存储的设备注册表信息 image

Shadow

Shadow服务用途

设备的影子 是用于存储和检索设备的当前状态信息的 JSON 文档。Device Shadow 服务可以为您连接到 AWS IoT 的每台设备保留一个影子。您可以使用该影子通过 MQTT 或 HTTP 获取和设置设备的状态,无论该设备是否连接到 Internet。每台设备的影子都由相应事物的名称唯一标识。 image

  • 设备影子保留每台设备的最后报告状态和期望的未来状态,即便设备处于离线状态。
  • 通过 API 或使用规则引擎,获取设备的最后报告状态或设置期望的未来状态。
  • 应用程序可以设置设备的期望未来状态,而无需说明设备的当前状态。AWS IoT 将比较期望未来状态和最后报告状态之间的差异,并命令设备"弥补差异"。
  • 设备 SDK 能够轻松地同步其状态及其影子,并响应通过影子设置的期望的未来状态。
  • 设备影子免费存储设备状态多达一年。如果至少每年更新一次状态,则设备影子将永久保留状态;否则状态将过期。

影子服务

设备影子服务使用MQTT话题,便于应用和设备之间的通信,下面是相关的MQTT QoS 1话题:

$aws/things/{thingName}/shadow/update

$aws/things/{thingName}/shadow/get

$aws/things/{thingName}/shadow/delete

$aws/things/{thingName}/shadow/update/accepted

$aws/things/{thingName}/shadow/update/rejected

$aws/things/{thingName}/shadow/update/delta

$aws/things/{thingName}/shadow/get/accepted

$aws/things/{thingName}/shadow/get/rejected

$aws/things/{thingName}/shadow/delete/accepted

$aws/things/{thingName}/shadow/delete/rejected

设备SDK(C-SDK、JS-SDK)将影子功能内置在设备中,能够使设备与影子服务之间自动同步状态。

控制模型

image 控制灯泡 image

工作原理

image

image

1.连接着的 Led 灯发送封装在MQTT消息中的 reported 状态 『off』 到 AWS IoT 2.AWS IoT 通过 led 灯使用的证书来确定它所属的虚拟事物 3.AWS IoT 将 reported 状态保存在设备影子 JSON 文件中 4.一条 AWS IoT rule 正监控着 led 的 off 状态,它发送一个消息到某个 SNS topic 5.某 application 收到 SNS 消息。用户将 led 期望状态(desired state)设置为 on 6. AWS IoT 收到该消息,它更新设备影子中的 desired state,同时发送包含期望状态的 message 到某些topic。此时,reported 和 desired 状态是 『Out of Sync』的 7. led 收到 delta 消息,开始根据其中的 desired status 来设置其实际状态 8. led 将其状态设置为 on,向 MQTT topic 发送新的 reported 状态 9. AWS IoT 更新设备影子,现在该设备的 reported 和 desired 状态一致了

格式

image

关键属性

image

影子文档属性

设备的影子文档具有以下属性:

  • state
  • desired 事物的预期状态。应用程序可以向本文档部分写入数据来更新事物的状态,且无需直接连接到该事物。

  • reported 事物的报告状态。事物可以向本文档部分写入数据,以报告其新状态。应用程序可以读取本文档部分,以确定事物的状态。

  • metadata 有关存储在文档 state 部分的数据的信息,其中包括 state 部分中每个属性的时间戳(以 Epoch 时间表示),让您能够确定它们的更新时间。

  • timestamp 指明 AWS IoT 传输消息的时间。通过在消息中使用时间戳并对 desired 或 reported 部分中的不同属性使用时间戳,事物可以确定已更新项目的存在时间,即使它不具有内部时钟特性。

  • clientToken 特定于设备的字符串,让您能在 MQTT 环境中将响应与请求关联起来。

  • version 文档版本。文档每次更新时,此版本号都会递增。用于确保正在更新的文档为最新版本。

影子文档语法

请求结构

{
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        },
        "reported": {
            "attribute1": integer1,
            "attribute2": "string1",
            ...
            "attributeN": boolean1
        }
    }
    "clientToken": "token",
    "version": version
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

响应状态

{
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        },
        "reported": {
            "attribute1": integer1,
            "attribute2": "string1",
            ...
            "attributeN": boolean1
        },
        "delta": {
            "attribute3": integerX,
            "attribute5": "stringY"
        }
    },
    "metadata": {
        "desired": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        },
        "reported": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        }
    },
    "timestamp": timestamp,
    "clientToken": "token",
    "version": version
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

错误响应

{
    "code": error-code,
    "message": "error-message",
    "timestamp": timestamp,
    "clientToken": "token"
}
1
2
3
4
5
6

预留主题

aws Iot预留了一些主题,预留的主题以$开头。除非下面列出的主题之外,不支持用于进行发布和订阅。在任何其他以 $ 开头的主题中尝试发布或订阅将导致连接被终止。

主题 允许的操作 描述
$aws/events/presence/connected/clientId Subscribe 当使用特定客户端 ID 的 MQTT 客户端连接至 AWS IoT 时,AWS IoT 将向此主题发布。有关更多信息,请参阅 连接/断开连接事件。
$aws/events/presence/disconnected/clientId Subscribe 当使用特定客户端 ID 的 MQTT 客户端与 AWS IoT 断开连接时,AWS IoT 将向此主题发布。有关更多信息,请参阅 连接/断开连接事件。
$aws/events/subscriptions/subscribed/clientId Subscribe 当使用特定客户端 ID 的 MQTT 客户端订阅 MQTT 主题时,AWS IoT 将向此主题发布。有关更多信息,请参阅 订阅/取消订阅事件。
$aws/events/subscriptions/unsubscribed/clientId Subscribe 当使用特定客户端 ID 的 MQTT 客户端取消订阅 MQTT 主题时,AWS IoT 将向此主题发布。有关更多信息,请参阅 订阅/取消订阅事件。
$aws/things/thingName/shadow/delete 发布/订阅 设备或应用程序向此主题发布消息以删除影子。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#delete-pub-sub-topic。
$aws/things/thingName/shadow/delete/accepted Subscribe 当一个影子被删除时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#delete-accepted-pub-sub-topic。
$aws/things/thingName/shadow/delete/rejected Subscribe 当删除影子的请求遭拒时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#delete-rejected-pub-sub-topic。
$aws/things/thingName/shadow/get 发布/订阅 应用程序或事物向此主题发布空消息来获取影子。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html。
$aws/things/thingName/shadow/get/accepted Subscribe 当获取影子的请求获批时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#get-accepted-pub-sub-topic。
$aws/things/thingName/shadow/get/rejected Subscribe 当获取影子的请求遭拒时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#get-rejected-pub-sub-topic。
$aws/things/thingName/shadow/update 发布/订阅 事物或应用程序向此主题发布消息以更新影子。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#update-pub-sub-topic。
$aws/things/thingName/shadow/update/accepted Subscribe 当影子更新成功时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#update-accepted-pub-sub-topic。
$aws/things/thingName/shadow/update/rejected Subscribe 当影子更新遭拒时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#update-rejected-pub-sub-topic。
$aws/things/thingName/shadow/update/delta Subscribe 当检测到影子的“reported”部分与“desired”部分之间存在差异时,Device Shadow 服务将向此主题发送消息。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#update-delta-pub-sub-topic。
$aws/things/thingName/shadow/update/documents Subscribe 每次影子更新成功执行时,AWS IoT 都会向该主题发布状态文档。有关更多信息,请参阅 http://docs.aws.amazon.com/iot/latest/developerguide//device-shadow-mqtt.html#update-documents-pub-sub-topic。

Sample 程序

basicPubSub.py

这个程序可以作publish也可以作subscribe,或者同时运行。

当publish时 每隔1s产生一个消息

loopCount = 0
while True:
    if args.mode == 'both' or args.mode == 'publish':
        message = {}
        message['message'] = args.message
        message['sequence'] = loopCount
        messageJson = json.dumps(message)
        myAWSIoTMQTTClient.publish(topic, messageJson, 1)
        if args.mode == 'publish':
            print('Published topic %s: %s\n' % (topic, messageJson))
        loopCount += 1
    time.sleep(1)

1
2
3
4
5
6
7
8
9
10
11
12
13

当作subscribe时,由于注册了calback函数,在收到消息时候会有一个调用

def customCallback(client, userdata, message):
    print("Received a new message: ")
    print(message.payload)
    print("from topic: ")
    print(message.topic)
    print("--------------\n\n")


# Connect and subscribe to AWS IoT
myAWSIoTMQTTClient.connect()
if args.mode == 'both' or args.mode == 'subscribe':
    myAWSIoTMQTTClient.subscribe(topic, 1, customCallback)
time.sleep(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14

输出如下:

2018-08-16 17:23:51,459 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-08-16 17:23:56,435 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [message] event
2018-08-16 17:23:56,435 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [message] event
Received a new message: 
b'{"message": "Hello World!", "sequence": 18}'
from topic: 
sdk/test/Python
--------------

1
2
3
4
5
6
7
8
9

basicPubSubAsync.py

注意ackCallback与messageCallback区别

ackCallback - Callback to be invoked when the client receives a SUBACK. Should be in form messageCallback - Function to be called when a new message for the subscribed topic comes in.

SUBACK: 服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。简单理解为服务器端通知订阅客户端"我知道你要订阅了"

详细参考:https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/0309-SUBACK.html

异常

sample程序可能会遇到exception,这多数是授权策略引起的。开发调试状态下

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14