使用Amazon AWS IoT Shadow Service

材料准备

  • Ameba x 1
  • Led x 1

范例说明

  • 简介 Amazon AWS IoT是一套云端服务,如同Amazon网站上描述: AWS IoT 是一种让您能够将装置连接至 AWS 服务和其他装置、保护资料和互动安全、处理和对装置资料采取动作,以及即使离线也能让应用程式与装置互动的平台。 (from https://aws.amazon.com/tw/iot/how- it-works/) 底下是AWS IoT的架构图: 1 (Picture from http://docs. aws.amazon.com/iot/latest/developerguide/aws-iot-how-it-works.html) 图中左上方的Things可以想成是Ameba,它与MQTT Message Broker建立起TLS加密的Channel之后,经由MQTT Protocol沟通。在Message Broker背后有Thing Shadows,可以让Ameba离线时,仍能让控制端留下讯息,在下一次Ameba连线时,Thing Shadow会将讯息传出。 架构里的Rules Engine可以针对Thing的行为做限制,也可以接上Amazon的其它服务,这部份不在这次的范例讨论里。
  • 使用AWS IoT主控台 要使用AWS IoT,首先需要开通AWS IoT的服务,你可以在这边找到登入与注册的讯息:https:/ /aws.amazon.com/ 开通服务需要填信用卡号来确认使用者,并且现在(2016/06/27)开通服务会在第一年享有优惠,在某个流量以内不收费,或是可以设置流量警示避免缴交不预期的费用。详细情形请参考网站内容说明。 登入之后,会进入Amazon Management Console,可以看到有很多的Service,点选IoT Core 2 会进入AWS IoT的首页,如果是第一次使用,会看到底下的简介画面。 Amazon的service为了效率考量分了好几个区域,让使用者可以选较近的server使用,为了确保使用品质,我们先点右上角使用者名称旁边的地区选项: 3 接着选择离自己近的区域 4 选好之后,我们再点选 “Get started” 5 则会带入AWS IoT 主页 5 5 左栏有一个“Manage”栏位,而且底下有一个“Things”项目,我们选择它,右边则点击“Register a thing” 6 进入下一页,点击“Create a single thing” 6 我们在Name栏位填入 thing的名称为 “ameba”,属性可以用来定义 ameba的状态,ameba可以更新这些状态,控制端也可以尝试要求ameba切换到控制端想要的状态。这里我们填入属性名称为led,值填入0,让ameba可以更新一个led的状态。设定完成之后,点选 “Next” 7 进入下一页我们先点选“Create thing witohut certificate” 8 之后我们能看到一个命名为ambea的Thing被成功创造出来 8 接着我们要开始创建一个Policy,点选左边栏位Secure底下的“Policies”,并在且右边页面点击“Create a policy” Policy的用途是限制thing的功能,可以限制thing可以执行的MQTT动作,或是限制特定的topic,更多policy的用法可以参考:http://docs.aws.amazon.com/iot/latest/developerguide/authorization.html 8 这里我们先不作限制,让整个流程成功之后再调整这部份。我们将policy的名称填入 “amebaPolicy”,Action填入 “iot:*”,Resources填入 “*”,并在后面的 “Allow”打勾。填完之后点选 “Create”。 9 就完成Policy的设定: 10 接着我们要设定TLS所需的certificate,点选 “Create a certificate”,点击左栏”Secure-> certificates”,并且在右边页面点选”Create a certificate” 11 这里可以选择自己定义的certificate,或是网站帮你产生。我们点选 “1-Click certificate create”让网站帮我们产生。 12 接着会产生四个连结,让我们可以下载 public key,private key,certificate 与 rootCA。我们将这四个档案下载。并且点击”Done”,回到certificates主页 13 在certificates主页右上方有一个”Actions”下拉选单,点选”Attach policy” 15 15 选择刚刚创造的“AmebaPolicy”接着点击“Attach” 接着再回到certificates主页右上方”Actions”下拉选单,点选”Attach thing”,出现下图视窗时选择刚创建的thing “ameba”,接着点击“Attach” 16 16 然后我们要启用certificate,回到certificates主页并且点选certificate之后,在右边的Actions下拉选单里,点选 “Activate”,则此certificate将开始启用 17 回到左边栏位,选择”Manage->Things”,点击刚新建的ameba thing 18 进入ameba thing的页面后,在左边选页选择“Interact”,可以看到我们设定Amazon Alexa所需的Rest API Endpoint及一些资讯: — REST API endpoint: 里面的值是“https://a1a7oo4baosgyy.iot.us-east-1.amazonaws.com/things/ameba/shadow”,其中“a1a7oo4baosgyy.iot.us-east-1.amazonaws. com”就是我们可以使用的MQTT Broker server的位址 — MQTT topic:里面的值是 “$aws/things/ameba/shadow/update”,代表如果我们想使用AWS IoT Shadow的服务,我们的MQTT topic就得填这个值。但如果我们只想用MQTT的功能,则可以使用其它值。这边我们建议使用 “$aws/things/ameba/shadow/update”
  • 设定Ameba 我们打开范例 “File” -> “Examples” -> “AmebaMQTTClient” -> “amazon_awsiot_basic” 首先需要先填入Ameba要连上的AP的ssid与password 22 接着填入thing的名称,这边我们填入 “ameba”,这个名称会自动带入与thing名称有关的字串里。 23 接着填入MQTT Broker server的位址,这个位址可以在AWS IoT主控台里找到,它会在我们新增的thing的资讯栏里面,这里我们填入”a1a7oo4baosgyy.iot.us-east-1.amazonaws.com24 接着我们填入TLS会用到的root CA,root CA我们刚刚已在certificate主页下载,我们可以下载确认一下root CA是否与sketch的root CA相同: 25 接着我们要填入我们在AWS IoT主控台新增的certificate(通常称之为client certificate),档名结尾为“-certificate.pem.crt” (Ex. “efae24a533-certificate.pem.crt”) ,我们可以用文字编辑器打开这个档案,会发现它与sketch的内容不太一样,我们需要将它调整成字串格式: – 每行后面需要加上换行符号 \n – 每行前后需要加上双引号 – 为了将字串串接,在行尾加上 \ – 最后一行以分号结束 27 我们在AWS IoT主控台新增certificate时,还有private key的资讯,我们将它填入,一样要转成字串格式: 28 到这边就设定完成了
  • 编译并执行 我们将sketch编译并上传至Ameba之后,按下reset按钮,打开serial monitor看执行的结果 29 1. 第一步会先连上AP并取得IP Address 2. 接着会尝试连上MQTT Broker server,这步会花比较久的时间。会看到log里出现验证certificate的资讯,最后建立TLS连线成功,显示 “connected” 3. 连线上之后,Ameba会publish目前的状态,topic 为 “$aws/things/ameba/shadow/update”,而payload为AWS IoT Shadow的JSON格式。 AWS IoT Shadow的格式可以参考这里:http: //docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-document-syntax.html这里Ameba只有led的状态,这个状态与我们在AWS IoT主控台在新增thing时所添加的状态是一样的名称。这里我们将 “led” 的状态填入1,代表将led点亮。 这里Ameba只有led的状态,这个状态与我们在AWS IoT主控台在新增thing时所添加的状态是一样的名称。这里我们将 “led” 的状态填入1,代表将led点亮 此时我们可以回到新增的ameba thing的页面,在栏位左边点击“Shadow”,ameba thing右方资讯栏看到资讯已更新,会看到“Last update”的地方会是最近几分钟的时间,并且“Shadow status” 的内容里会看到ameba上传的资讯。 30 如果我们想控制ameba让led关掉,可以点选右上方的 “Edit” 31 点选之后,会出现 “Shadow state” 的文字方块,里面已经有预设的内容 我们将文字方块的内容改成:
    {
      "desired": {
        "led": 0
      }
    }
    
    代表我们希望将 “led” 的状态改为 0,改完之后点选 “Save” 33 等一会儿会看到 “led” 的相关状态都变成 0了,并且 “Last update” 又有一笔新的更新 34 此时回到 Serial Monitor会看到新的讯息 1. 进来了一笔标题为 “$aws/things/ameba/shadow/update/accepted” 的讯息,内容有刚刚我们在AWS IoT主控台填写的内容 2. Ameba收到前一笔讯息时,解析它的内容,发现 “led” 状态变成0,于是将led关掉,并且publish新的状态上去 3. 同时进来另外一笔标题为 “$aws/things/ameba/shadow/update/delta”的内容 4. 最后MQTT Broker又送一笔标题 “$aws/things/ameba/shadow/update/accepted”的讯息,回应ameba最新一笔的publish 35 这个过程到这边结束,我们总共使用了 AWS IoT主控台,设定了TLS加密所需的certificate,也设定了MQTT Brokder,最后使用AWS IoT Shadow操作与更新ameba的状态。 Amazon提供了详细的文件,可以在这里找到更多相关资讯:http:// docs.aws.amazon.com/iot/latest/developerguide/

程式码说明

整份程式码使用了基本的MQTT架构,除了AWS IoT的MQTT Broker Server与TLS certificate设定可以参考前面的说明之外,程式码说明如下
  • 设定led状态 这部份是一般的GPIO应用,预设led_pin为10,led_state为1
    pinMode(led_pin, OUTPUT);
    digitalWrite(led_pin, led_state);
    
  • 连线至AP 这部份是一般的wifi连线程式码,没有不同的地方
  • 设定certificate 这部份就有点不同,其中我们的wifiClient的型态是
    WiFiSSLClient wifiClient;
    
    WiFiSSLClient继承了Client,所以也可以当作PubSublicant的constructor参数 在连线之前,我们设定TLS相关的certificate
    wifiClient.setRootCA((unsigned char*)rootCABuff);
    wifiClient.setClientCertificate((unsigned char*)certificateBuff, (unsigned char*)privateKeyBuff);
    
  • 设定MQTT Broker server 接着MQTT PubClient设定MQTT Broker server并且连线
    client.setServer(mqttServer, 8883);
    client.setCallback(callback);
    
    注意到这边的port是8883,一般来说,如果MQTT底层走的是TLS协定,使用的port会是8883
  • 连线至MQTT Broker server 进入loop()之后,会呼叫reconnect()并且尝试连线,这边也是log里出现验证certificate的地方:
    while (!client.connected()) {
    
  • Subscribe & Publish 连线成功之后,注册要倾听的topic
    for (int i=0; i<5; i++) {
      client.subscribe(subscribeTopic[i]);
    }
    
    常用的topic有这些 “$aws/things/ameba/shadow/update/accepted”, “$aws/things/ameba/shadow/update/rejected”, “$aws/things/ameba/shadow/update/delta”, “$aws/things/ameba/shadow/get/accepted”, “$aws/things/ameba/shadow/get/rejected” 简易的说明可以参考这里: http://docs.aws.amazon.com /iot/latest/developerguide/thing-shadow-data-flow.html 注册完之后,我们publish目前的状态
    sprintf(publishPayload, "{\"state\":{\"reported\":{\" led\":%d}},\"clientToken\":\"%s\"}", led_state, clientId);
    client.publish(publishTopic, publishPayload);
    
  • 倾听topic并做出回应 我们在callback里倾听先前注册的5个topic,并且检查是否有 “/shadow/get/accepted
    if (strstr(topic, "/shadow/get/accepted") != NULL) {
    
    如果有的话,代表控制端送了讯息过来,我们解析里面的内容,如果led状态与现在不同,则publish新的状态
    updateLedState(desired_led_state);
    
请先确认已安装QQ通讯软体