電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>物聯(lián)網(wǎng)人類活動(dòng)識(shí)別網(wǎng)絡(luò)應(yīng)用

物聯(lián)網(wǎng)人類活動(dòng)識(shí)別網(wǎng)絡(luò)應(yīng)用

2022-12-15 | zip | 0.13 MB | 次下載 | 免費(fèi)

資料介紹

描述

大家好,我是 Ivan Fardin,我是羅馬 Sapienza 大學(xué)計(jì)算機(jī)科學(xué)工程碩士的學(xué)生,這個(gè)項(xiàng)目作為物聯(lián)網(wǎng) 19-20課程的一部分而開(kāi)發(fā)的。

在本文中,我將向您展示如何使用用戶設(shè)備的加速度傳感器根據(jù)人群感應(yīng)技術(shù)收集的值來(lái)設(shè)置一個(gè)基于 IoT MQTT 的基于云的人類活動(dòng)識(shí)別 Web 應(yīng)用程序系統(tǒng)。

概述

該項(xiàng)目包括:

  • 一個(gè)網(wǎng)絡(luò)應(yīng)用程序,它從用戶手機(jī)的加速傳感器收集和顯示數(shù)據(jù)
  • 使用 AWS IoT 實(shí)現(xiàn)的 IoT MQTT 基于云的后端系統(tǒng)

假設(shè)運(yùn)動(dòng)最多為 0.5 Hz(即每分鐘 30 步),理論上 1 Hz(即每秒 1 條消息)的采樣頻率足以識(shí)別用戶是否靜止不動(dòng)。

所有代碼都可以在GitHub 存儲(chǔ)庫(kù)中找到。

建筑學(xué)

pYYBAGOYIQOALM0eAABbpUhxRPs584.png
建筑學(xué)
?

讓我們通過(guò)分析圖中的每個(gè)組件開(kāi)始詳細(xì)介紹。

用戶可以通過(guò)以下網(wǎng)站上的瀏覽器訪問(wèn)Web 應(yīng)用程序,并且該應(yīng)用程序獨(dú)立于操作系統(tǒng),因此可以將手機(jī)、平板電腦、臺(tái)式機(jī)和筆記本電腦等不同設(shè)備連接到后端。它利用通用傳感器 API從移動(dòng)設(shè)備的加速傳感器收集數(shù)據(jù)。通用傳感器 API 是一種傳感器框架,可在安全上下文(即 HTTPS)中將傳感器設(shè)備暴露給 Web 平臺(tái)。

傳感器值或由此產(chǎn)生的人類活動(dòng)通過(guò)MQTT (一種輕量級(jí)且被廣泛采用的針對(duì)特定主題的受限設(shè)備設(shè)計(jì)的消息傳遞協(xié)議)使用與網(wǎng)站訪問(wèn)相關(guān)聯(lián)的唯一 ID(身份)傳輸?shù)皆苹A(chǔ)設(shè)施。

MQTT 是使用Eclipse Paho JavaScript Client實(shí)現(xiàn)的,這是一個(gè)用Javascript編寫的基于瀏覽器的 MQTT 客戶端庫(kù),它使用 WebSockets(一種通信協(xié)議,通過(guò)單個(gè) TCP/IP 連接提供全雙工通信通道)連接到 MQTT 代理。

為什么使用 WebSocket 上的 MQTT ?由于該應(yīng)用程序是 Web 應(yīng)用程序,因此它存在于瀏覽器中,并且基于 WebSocket 的 MQTT 允許將 MQTT 數(shù)據(jù)直接發(fā)送和接收到 Web 瀏覽器中。

通過(guò) Paho 發(fā)送的消息取決于用戶選擇的模式來(lái)識(shí)別活動(dòng),它們是:

  • 如果人類活動(dòng)識(shí)別模型由云端執(zhí)行,則為原始數(shù)據(jù)
  • 如果人類活動(dòng)識(shí)別模型由用戶設(shè)備執(zhí)行,則產(chǎn)生的人類活動(dòng)

后端是使用AWS IoT實(shí)現(xiàn),它在 Internet 連接的設(shè)備和 AWS 云之間提供安全的雙向通信。設(shè)備與 AWS 云之間的通信由AWS IoT 消息代理根據(jù)發(fā)布-訂閱模式進(jìn)行處理。

AWS IoT 消息代理為設(shè)備和 AWS IoT 應(yīng)用程序提供了一種安全機(jī)制,可以通過(guò)將消息從發(fā)布客戶端發(fā)送到訂閱客戶端來(lái)相互發(fā)布和接收連接 AWS IoT 客戶端的消息。客戶端通過(guò)在主題上發(fā)布消息來(lái)發(fā)送數(shù)據(jù),并通過(guò)訂閱主題來(lái)接收消息。當(dāng)消息代理接收到來(lái)自發(fā)布客戶端的消息時(shí),它會(huì)將消息轉(zhuǎn)發(fā)給所有訂閱該主題的客戶端。

此外,AWS IoT 提供了創(chuàng)建規(guī)則的可能性,這些規(guī)則定義了一個(gè)或多個(gè)要根據(jù) MQTT 消息主題執(zhí)行的操作。通過(guò)這種方式,我通過(guò)創(chuàng)建一個(gè)規(guī)則來(lái)實(shí)現(xiàn)云計(jì)算,在該規(guī)則中,代理將來(lái)自 Web 應(yīng)用程序設(shè)備的所有傳入消息轉(zhuǎn)發(fā)到指定的AWS Lambda函數(shù)。這會(huì)詳細(xì)說(shuō)明傳入的數(shù)據(jù)并將它們插入到代表架構(gòu)持久層的AWS DynamoDB表中。

最后,Web 應(yīng)用程序連接到 AWS DynamoDB 服務(wù),以根據(jù)所選模式檢索和顯示設(shè)備數(shù)據(jù)和最后一小時(shí)的結(jié)果活動(dòng),并連接到代理發(fā)送數(shù)據(jù),如果啟用了云計(jì)算, 從 Lambda 函數(shù)接收實(shí)時(shí)數(shù)據(jù)。

?

AWS 配置

首先,如果您沒(méi)有 AWS 賬戶,您需要?jiǎng)?chuàng)建一個(gè)。作為一名學(xué)生,我有一個(gè)AWS 教育,它免費(fèi)提供對(duì)云資源的有限訪問(wèn)。

如果您像我一樣擁有 AWS 教育賬戶,請(qǐng)確保所選區(qū)域是 us-east-1(北弗吉尼亞),這是此類賬戶唯一可用的區(qū)域,否則后端將無(wú)法工作。

注冊(cè)或登錄后,請(qǐng)轉(zhuǎn)到下一部分。

動(dòng)態(tài)數(shù)據(jù)庫(kù)

后端實(shí)施的一個(gè)良好起點(diǎn)可能是創(chuàng)建AWS DynamoDB表。

因此,在 AWS 控制臺(tái)中找到 DynamoDB 服務(wù)并單擊它。然后點(diǎn)擊創(chuàng)建表并填寫如下表格,然后按創(chuàng)建。

poYBAGOYIQqAA8l1AAJvK-HlK5c966.png
動(dòng)態(tài)數(shù)據(jù)庫(kù) - 1
?

為了與 web 應(yīng)用部分中的代碼保持一致,我將使用IddateTime但當(dāng)然您可以將任何屬性作為分區(qū)和排序鍵,以及決定不使用排序鍵。

創(chuàng)建表后,您可以滾動(dòng)概覽選項(xiàng)卡獲取關(guān)聯(lián)的 ARN

poYBAGOYIRyAPJDFAAIBVMzDrSM383.jpg
動(dòng)態(tài)數(shù)據(jù)庫(kù) - 2
?

通過(guò)單擊項(xiàng)目選項(xiàng)卡,您可以查看表中存在哪些元素。

pYYBAGOYIR-AbOaTAAHpaRcT9Co434.png
DynamoDB - 3
?

由于加速度傳感器的采樣頻率為 1 Hz,并且值會(huì)立即傳輸以進(jìn)行實(shí)時(shí)識(shí)別,因此表格的大小將隨著使用而大幅增加。這可能是一個(gè)性能問(wèn)題,但要記住 Web 應(yīng)用程序的功能,我只需要持久性來(lái)顯示最后一小時(shí)的數(shù)據(jù),因此我可以在這段時(shí)間間隔后刪除它們以提高性能。為此,DynamoDB 提供了生存時(shí)間(TTL) 功能,該功能允許定義表中的項(xiàng)目何時(shí)過(guò)期,以便可以自動(dòng)從數(shù)據(jù)庫(kù)中刪除它們。

因此,在項(xiàng)目選項(xiàng)卡中單擊操作管理 TTL。

poYBAGOYISiAWyr1AAG43pwSj1s837.png
DynamoDB - 4
?

在這里放置您決定用作 TTL 的屬性,然后單擊Continue

poYBAGOYISyAKNiNAAIALQWzLwg709.png
DynamoDB - 5
?

沒(méi)有什么比這更簡(jiǎn)單了,您的數(shù)據(jù)庫(kù)已準(zhǔn)備就緒。

?

拉姆達(dá)

既然你的數(shù)據(jù)庫(kù)已經(jīng)準(zhǔn)備好了,讓我們看看如何填充它。請(qǐng)記住,當(dāng) MQTT 消息到達(dá)AWS IoT Broker時(shí),它會(huì)檢查主題是否與您選擇調(diào)用 Lambda 函數(shù)的主題匹配。AWS Lambda是一項(xiàng)計(jì)算服務(wù),讓您無(wú)需預(yù)置或管理服務(wù)器即可運(yùn)行代碼,并且僅在需要時(shí)執(zhí)行您的代碼并自動(dòng)擴(kuò)展。

創(chuàng)建 Lambda 函數(shù)搜索并在 AWS 控制臺(tái)中選擇 Lambda 服務(wù)。

在其主頁(yè)中單擊創(chuàng)建功能

pYYBAGOYITaAINu6AABuJbnnoO4143.jpg
AWS Lambda - 1
?

然后為它選擇一個(gè)名稱,作者從頭開(kāi)始選項(xiàng),因?yàn)槲业膶?shí)現(xiàn)非常簡(jiǎn)單,以及編程語(yǔ)言(在我的例子中我選擇了Python 3.7 )。最后點(diǎn)擊創(chuàng)建函數(shù)

poYBAGOYIUCAV_9NAAKE_RfTOAk413.png
AWS Lambda - 2
?

好的,現(xiàn)在您必須在編輯器中輸入以下代碼:

  • 在邊緣計(jì)算的情況下,將在 DB 中插入與傳入 MQTT 消息對(duì)應(yīng)的項(xiàng)目
  • 在云計(jì)算的情況下,將根據(jù)傳入的MQTT消息中的值執(zhí)行Human Activity Recognition的模型,在DB中插入相應(yīng)的項(xiàng)目并將MQTT消息發(fā)送回客戶端以獲得實(shí)時(shí)結(jié)果
pYYBAGOYIUuAcD16AAEuTijP_wE563.jpg
AWS Lambda - 3
?
import json
import boto3
import time

dynamodb = boto3.resource('dynamodb', region_name='')
table = dynamodb.Table('')

def lambda_handler(event, context):
  # Data expires after 1 hour (3600 s) and few minutes (400 s)
  # Time in Unix epoch
  ttl = int(time.time()) + 4000

  # Check if edge computation
  if "isStanding" in event:
    table.put_item(
      Item={
        "Id": event["clientID"],
        "dateTime": event["dateTime"],
        "isStanding": event["isStanding"],
        "computation": "edge",
        "TTL": ttl
    }
  );

  # Else cloud computation
  else:
    isStanding = True
    x2 = event["x2"]
    y2 = event["y2"]
    z2 = event["z2"]

    if((abs(x2 - event["x1"])*0.67 > 0.292) or
       (abs(y2 - event["y1"])*0.7 > 0.145) or 
       (abs(z2 - event["z1"])*0.67 > 0.45)):
      isStanding = False

    clientID = event["clientID"]
    table.put_item(
      Item={
        "Id": clientID,
        "dateTime": event["dateTime"],
        "x": str(x2),       # DynamoDB does not support float type
        "y": str(y2),
        "z": str(z2),
        "isStanding": isStanding,
        "computation": "cloud",
        "TTL": ttl
      }
    );

    client = boto3.client('iot-data', region_name='')
    # Change topic, qos and payload
    response = client.publish(
      topic = "" + clientID,
      qos = 1,
      payload = json.dumps({
        "x": x2,
        "y": y2,
        "z": z2,
        "isStanding": isStanding
      })
    )

?

認(rèn)知和 IAM

現(xiàn)在,您需要?jiǎng)?chuàng)建一個(gè)AWS Cognito Identity Poll,授予用戶訪問(wèn) DynamoDB 服務(wù)和使用 AWS IoT 的 MQTT 操作的權(quán)限。

在 AWS 控制臺(tái)中搜索并選擇 Cognito 服務(wù)。

在其主頁(yè)中,按Create Identity Poll按鈕并填寫如下表格,然后單擊Create Pool ,然后單擊Allow 。

?
?
?
pYYBAGOYyJCAFfTEAALTOGfGMqI022.png
?
1 / 2 ?認(rèn)知 - 1
?

因此,單擊示例代碼選項(xiàng)卡以查看您的池 ID。

poYBAGOYyJSACsKbAAEjGGbxXeo911.jpg
認(rèn)知 - 3
?

現(xiàn)在移動(dòng)到IAM 服務(wù)頁(yè)面并單擊角色

pYYBAGOYyJeAGd6cAAA3Bpeqvac145.png
IAM - 1
?

在這里搜索剛剛創(chuàng)建的新的未經(jīng)授權(quán)的 Cognito 角色并單擊它。

pYYBAGOYyJuARh62AAKjJ6W_bBA947.jpg
IAM - 2
?

然后按附加策略按鈕

poYBAGOYyJ2AegCCAAECwFSY4ig371.jpg
IAM - 3
?

并搜索DynamoDBFullAccess ,選擇它并按下附加策略按鈕。

pYYBAGOYyKeAG0ofAAKU0demhFw281.png
IAM - 4
?

您的Cognito 身份投票現(xiàn)已準(zhǔn)備好用于訪問(wèn)您的 DynamoDB。

要完成,您必須創(chuàng)建并附加 IoT 策略,以執(zhí)行 MQTT 消息的連接、訂閱、發(fā)布等操作。

要?jiǎng)?chuàng)建策略,請(qǐng)?jiān)俅螁螕?/font>附加策略按鈕,然后單擊創(chuàng)建策略( IAM步驟 3 和 4 的圖片可能很有用)。

在這里移動(dòng)JSON選項(xiàng)卡

poYBAGOYyKmAaZIwAAEhGZkSHD8067.png
IAM - 5
?

并在編輯器中粘貼以下 JSON,將區(qū)域、帳戶 ID 和主題字段替換為您的

pYYBAGOYyKyAeuKfAAF2eELfNYI389.jpg
IAM - 6
?
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": [
        "arn:aws:iot:::client/${iot:ClientId}"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive"
      ],
      "Resource": [
        "arn:aws:iot:::topic/"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
        "arn:aws:iot:::topicfilter/"
      ]
    }
  ]
}

然后,按Review policy并插入策略名稱和描述,然后單擊Create policy 。

poYBAGOYyLCAAfEuAAFZk4I9XSw367.png
IAM - 7
?

最終重復(fù) IAM 步驟 3 和 4 以將此新策略附加到未經(jīng)授權(quán)的角色。

大功告成,您的 Cognito Identity Poll 已準(zhǔn)備好用于訪問(wèn)您的 DynamoDB 和 IoT Core。

?

物聯(lián)網(wǎng)核心

您幾乎已經(jīng)完成了后端的設(shè)置,只是錯(cuò)過(guò)了使用AWS IoT Core創(chuàng)建事物對(duì)象的過(guò)程。

在 AWS 控制臺(tái)中找到 IoT Core 服務(wù)并單擊它。

在這里,您必須將您的設(shè)備連接到平臺(tái),因此請(qǐng)轉(zhuǎn)到Onboard并單擊Onboard a device中的Get started 。

pYYBAGOYyLOAO1yDAAGU0bP86Vg990.png
物聯(lián)網(wǎng)核心 - 1
?

然后選擇您連接到 AWS IoT 的方式,在本例中,我使用Linux平臺(tái)和Java編程語(yǔ)言,然后按 N ext 。

pYYBAGOYyLeAD3PvAAF-fZV4YcQ967.png
物聯(lián)網(wǎng)核心 -2
?

輸入你的東西的名字,然后繼續(xù)

poYBAGOYyLqAd4ZpAADaRxMcA_Q084.png
物聯(lián)網(wǎng)核心 -3
?

然后下載證書和私鑰和公鑰,然后進(jìn)行下一步。

pYYBAGOYyL2AQHWrAAFcqamSCdw589.png
物聯(lián)網(wǎng)核心 -4
?

您將在此處顯示配置和測(cè)試設(shè)備的教程,因此請(qǐng)按完成。你的東西已經(jīng)創(chuàng)建了:)

poYBAGOYyL-AM-MIAAE7wxXBSQE211.png
物聯(lián)網(wǎng)核心 -5
?

之后,記下唯一標(biāo)識(shí)您的事物的Amazon 資源名稱(ARN) 中的區(qū)域和賬戶 ID 。

ARN 具有以下一般格式:

  • arn:partition:service:region:account-id:resource-id
  • arn:partition:service:region:account-id:resource-type/resource-id
  • arn:partition:service:region:account-id:resource-type:resource-id

因此,從 IoT Core 初始頁(yè)面轉(zhuǎn)到Things ,選擇新創(chuàng)建的并單擊它。

poYBAGOYyMKAK39NAADHUwYd0ZI929.jpg
物聯(lián)網(wǎng)核心 -6
?

單擊設(shè)置并記下您的自定義端點(diǎn),該端點(diǎn)允許您通過(guò) REST API 連接到 AWS IoT(稍后將非常有用)。

pYYBAGOYyMSAZqK5AACevRBwM1E054.jpg
物聯(lián)網(wǎng)核心 -7
?

現(xiàn)在您需要編輯在創(chuàng)建事物時(shí)生成的策略,以允許您的客戶端通過(guò) MQTT 連接并與代理通信。

因此,從 IoT Core 初始頁(yè)面轉(zhuǎn)到Secure ,然后轉(zhuǎn)到Policies ,然后單擊與您的事物關(guān)聯(lián)的策略

pYYBAGOYyMuAXh55AAIXnQeJdHs471.jpg
物聯(lián)網(wǎng)核心 - 8
?

在此處單擊Edit policydocument 并重用 IAM 控制臺(tái)中使用的 JSON 將區(qū)域和賬戶 ID 字段替換為您之前使用的字段

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": [
        "arn:aws:iot:::client/${iot:ClientId}"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive"
      ],
      "Resource": [
        "arn:aws:iot:::topic/"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
        "arn:aws:iot:::topicfilter/"
      ]
    }
  ]
}

在哪里:

  • ${iot:ClientId}變量表示用于連接到 AWS IoT Core 消息代理的客戶端ID
  • *是主題名稱的通配符,相當(dāng)于 MQTT 協(xié)議中的 # 通配符

有關(guān) IoT 策略的更多信息,請(qǐng)參閱相關(guān)文檔。

現(xiàn)在,您必須向代理添加一條規(guī)則,以在傳入消息發(fā)布到指定主題時(shí)調(diào)用之前定義的 Lambda 函數(shù)。記下主題,稍后您將使用它。

為此,請(qǐng)轉(zhuǎn)到Act并按Create a rule按鈕。然后使用規(guī)則名稱和描述以及將過(guò)濾有關(guān)主題的傳入消息的 SQL 查詢填寫表格

poYBAGOYyNCAJ5HOAAFnsjhlF_k502.png
物聯(lián)網(wǎng)核心規(guī)則 - 1
?

滾動(dòng)頁(yè)面并按添加操作按鈕為規(guī)則設(shè)置操作

poYBAGOYyNOATpAfAAF3u9QWsYg336.png
物聯(lián)網(wǎng)核心規(guī)則 - 2
?

并選擇向 Lambda 函數(shù)發(fā)送消息。

pYYBAGOYyNeAJptLAAIDXBNsmjk168.png
物聯(lián)網(wǎng)核心規(guī)則 - 3
?

然后點(diǎn)擊頁(yè)面底部的Configure action ,選擇之前創(chuàng)建的函數(shù)

pYYBAGOYyNqAR8smAACo63HXO8I579.jpg
物聯(lián)網(wǎng)核心規(guī)則 - 4
?

最后,單擊添加操作,然后單擊創(chuàng)建規(guī)則以得出結(jié)論:您的后端終于準(zhǔn)備好了 :)

poYBAGOYyN2AEHjdAADxSHsTmt4530.png
物聯(lián)網(wǎng)核心規(guī)則 - 5
?

?

加速度計(jì)網(wǎng)絡(luò)應(yīng)用程序

一旦您設(shè)置了基于云的后端,就該進(jìn)行具有雙重作用的 Web 應(yīng)用程序開(kāi)發(fā):生成和顯示數(shù)據(jù)。如果選擇邊緣計(jì)算,它還必須在本地處理數(shù)據(jù)。

要實(shí)現(xiàn)這一點(diǎn),您需要一些HTML5Javascript的基礎(chǔ)知識(shí)(也可以選擇CSS )。

讓我們從index.html文件開(kāi)始,該文件包含 Javascript 可以使用的元素。

首先,您必須導(dǎo)入可選的 CSS 文件styles.css以及必要的SDK和腳本,包括AWSPaho MQTT的那些。

html>
<html>
  <head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixeden-stroke-7-icon@1.2.3/pe-icon-7-stroke/dist/pe-icon-7-stroke.min.css">
  <link rel="stylesheet" href="css/styles.css">

  <script src="js/main.js">script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">script>

  
  <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.1">script>
  <script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8">script>
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.7">script>

  <script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.16.min.js">script>
  <script src="js/aws.js">script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript">script>
  <script src="js/pahoMQTTClient.js">script>
head>

然后,在我的實(shí)現(xiàn)的主體部分,我使用了兩個(gè)按鈕允許用戶在Cloud 和 Edge Computing之間進(jìn)行選擇,另一個(gè)用于檢索最后一小時(shí)的數(shù)據(jù)


		

id="btns" class="buttonsAnimation"> id="cloudBtn" class="btn btn-primary btn-lg btn-custom">Cloud Computing id="edgeBtn" class="btn btn-primary btn-lg btn-custom">Edge Computing

id="historyBtn" class="hide"> class="btn btn-secondary btn-lg btn-custom">Show last hour values

在云計(jì)算的情況下顯示人類活動(dòng)識(shí)別結(jié)果和加速度計(jì)值的段落


		

id="measure" class="measure hide">

和四張卡片,以顯示以下形式的最后一小時(shí)值和活動(dòng)(當(dāng)然具有不同的 ID)


		
"historyChart" class="chart hide"> <div class="card"> <div class="card-body"> <div class="stat-widget-five"> <div class="stat-icon dib green-color"> <i class="pe-7s-graph2">i> div> <div class="stat-content"> <div class="dib"> <div class="stat-text">History Chartdiv> div> div> div> <canvas id="historyCanvas">canvas> div> div> </div> ... html>

我省略了一些不是成功完成任務(wù)的基本元素,但如果您有興趣,可以在我的GitHub 存儲(chǔ)庫(kù)中找到這些元素。

好吧,現(xiàn)在是時(shí)候討論由三個(gè) Javascript 文件組成的 Web 應(yīng)用程序的邏輯了:

  • aws.js
  • pahoMQTTClient.js
  • main.js

第一個(gè)包含兩個(gè)函數(shù),用于在具有 AWS IoT Core 的 Web 應(yīng)用程序中通過(guò) WebSocket 協(xié)議使用 MQTT,以便使用AWS Signature Version 4指定憑證。

第二個(gè)是一個(gè) Javascript 類,它使用 WebSockets 執(zhí)行與服務(wù)器的連接。此外,它還提供訂閱或取消訂閱 MQTT 主題、發(fā)布和接收 MQTT 消息以及與服務(wù)器斷開(kāi)連接的功能。實(shí)現(xiàn)非常簡(jiǎn)單,有關(guān) Paho MQTT 的更多信息可以在官方頁(yè)面上閱讀

類構(gòu)造函數(shù)在輸入中有兩個(gè)參數(shù)

  • 執(zhí)行 WebSocket 連接的請(qǐng)求 URL
  • 在 MQTT 通道中唯一標(biāo)識(shí)客戶端的客戶端 ID。
class PahoMQTTClient {
  constructor(requestUrl, clientId) {
    this.requestUrl  = requestUrl;
    this.clientId    = clientId;
    this.client      = null;
    this.isConnected = false;
  }

  ...
}

為了將客戶端連接到服務(wù)器,我編寫了以下函數(shù),它接收兩個(gè)回調(diào)作為參數(shù),當(dāng)連接成功或失敗時(shí)以及訂閱主題后收到 MQTT 消息時(shí)將調(diào)用它們。連接是使用SSL和可用于 AWS IoT 的更新版本的 MQTT 執(zhí)行的。請(qǐng)注意,在連接選項(xiàng)中還指定了訂閱后傳入消息的回調(diào),我添加了接收回調(diào)。

// Connect to the server
conn(callbackConnection, callbackReceive) {
  this.client = new Paho.MQTT.Client(this.requestUrl, this.clientId);
  var connectOptions = {
    onSuccess: () => {
      // Connect succeeded
      console.log("onConnect: connect succeeded");
      // In an arrow function "this" represents the owner of the function
      // while in a regular function "this" represents the object that calls the function
      this.isConnected = true;
      callbackConnection();
    },
    useSSL: true,
    timeout: 3,
    mqttVersion: 4,
    onFailure: function() {
      // Connect failed
      console.log("onFailure: connect failed");
      callbackConnection();
    }
  };

  // Set callback handlers
  this.client.onConnectionLost = onConnectionLost;
  this.client.onMessageArrived = onMessageArrived;

  // Connect the client
  this.client.connect(connectOptions);
  
  // Called when the client loses its connection
  function onConnectionLost(responseObject) {
    if (responseObject.errorCode !== 0)
    console.log("onConnectionLost:" + responseObject.errorMessage);
  }

  // Called when a message arrives
  function onMessageArrived(message) {
    console.log("onMessageArrived:" + message.payloadString);
    callbackReceive(message.payloadString);
  }
}

訂閱取消訂閱是很瑣碎的函數(shù)

// Subscribe to a topic
sub(topic) {
  console.log("Subscribing on topic " + topic);
  this.client.subscribe(topic);
}

// Unsubscribe to a topic
unsub(topic) {
  console.log("Unsubscribing on topic " + topic);
  this.client.unsubscribe(topic);
}

以及發(fā)布

// Publish a message on a topic
pub(message, topic) {
  console.log("Publishing message on topic " + topic);
  // QOS = 0 => Best effort, retained = false => Message delivered only to current subscriptions
  this.client.send(topic, message, 0, false);
}

我們錯(cuò)過(guò)與 AWS 后端連接的最后一步是提供憑證我們可以直接使用IAM

var host = "", region = "";
var credentials = new AWS.Credentials("", "", "");
var requestUrl = SigV4Utils.getSignedUrl(host, region, credentials);

認(rèn)知

// Initialize Amazon Cognito credentials provider
AWS.config.region      = '';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: '',
});

// Obtain credentials
AWS.config.credentials.get(function(){
  // Credentials will be available when this function is called
  var host       = "";
  var requestUrl = SigV4Utils.getSignedUrl(host, AWS.config.region, AWS.config.credentials);

  ...
});

選擇哪一個(gè)?Cognito 當(dāng)然是因?yàn)槲也幌牍_(kāi)我的憑據(jù)。

因此在main.js文件中,當(dāng)獲取憑證時(shí),使用上述 Javascript 文件的功能執(zhí)行 WebSocket 上的 MQTT 連接

var uuid       = createUUID();
var mqttClient = null;

// Initialize Amazon Cognito credentials provider
AWS.config.region      = '';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: '',
});

// Obtain credentials
AWS.config.credentials.get(function(){
  // Credentials will be available when this function is called
  var host       = "";
  var requestUrl = SigV4Utils.getSignedUrl(host, AWS.config.region, AWS.config.credentials);
  mqttClient     = new PahoMQTTClient(requestUrl, uuid);
  mqttClient.conn(callbackConnection, callbackReceive);
});

這兩個(gè)回調(diào)函數(shù)非常簡(jiǎn)單,但由于操作是異步的,所以是必要的。第一個(gè)通知全局環(huán)境連接嘗試已結(jié)束,第二個(gè)用于在啟用云計(jì)算時(shí)接收 MQTT 數(shù)據(jù)實(shí)時(shí)顯示給用戶。

// Callback for the MQTT client connection
function callbackConnection() {
  fired = true;

  // Check if the callback is invoked after that a button is pressed (slow connection)
  if(cloudBtnActivated || edgeBtnActivated)
    main();
}

// Callback for the MQTT client when a message is received after subscription
function callbackReceive(msg) {
  if(!cloudBtnActivated)  return;

  msg = JSON.parse(msg);
  setMeasureText('x: ' + msg.x + '
y: ' + msg.y + '
z: ' + msg.z + "
" + (msg.isStanding ? "You're standing" : "You're moving"));
}

其中cloudBtnActivatededgeBtnActivated是兩個(gè)全局標(biāo)志,分別表示是否激活了云計(jì)算按鈕或邊緣計(jì)算按鈕。

Web 應(yīng)用程序的一個(gè)關(guān)鍵軟件組件由通用傳感器 API構(gòu)成,它允許在上下文安全 (HTTPS) 時(shí)從用戶移動(dòng)設(shè)備的加速度計(jì)傳感器收集數(shù)據(jù)。

用法很簡(jiǎn)單,但是要讀取傳感器我們需要用戶的權(quán)限,所以首先檢查它是否被授予

navigator.permissions.query({ name: "accelerometer" }).then(result => {
  if (result.state != 'granted') {
    setMeasureText("Sorry, we're not allowed to access sensors on your device");
    return;
  }
  start();
}).catch(err => {
  setMeasureText("Integration with Permissions API is not enabled");
});

如果成功,調(diào)用 start 函數(shù),該函數(shù)將創(chuàng)建讀取數(shù)據(jù)的 Javascript 對(duì)象

var accelerometer = null;
var topic = "" + uuid;

function start() {
  if(accelerometer != null) {
    accelerometer.start();
    return;
  }
  try {
    // For cloud computing
    mqttClient.sub("" + uuid);
    // Read once per second
    accelerometer = new Accelerometer({ frequency: 1 });
    accelerometer.addEventListener('error', errorListener);
    accelerometer.addEventListener('reading', readListener);
    accelerometer.start();
  } catch (error) {
    // Handle construction errors
    setMeasureText(error.message);
  }
}

架構(gòu)部分所述,我以 1 Hz 的頻率采樣并立即訂閱該主題以接收云計(jì)算結(jié)果消息。請(qǐng)注意,try代碼塊在應(yīng)用程序的整個(gè)生命周期中執(zhí)行一次,以避免多次創(chuàng)建。

錯(cuò)誤監(jiān)聽(tīng)非常簡(jiǎn)單;它只是在應(yīng)顯示 HAR 結(jié)果的區(qū)域顯示錯(cuò)誤消息

function errorListener(event) {
  // Handle runtime errors
  setMeasureText(event.error.message);
}

相反,讀取偵聽(tīng)器更有趣,因?yàn)槌嗽趦煞N模式下發(fā)送 MQTT 消息之外,它還包含傳感器值的處理和 HAR 結(jié)果的后續(xù)顯示(在邊緣計(jì)算的情況下)。

function readListener(event) {
  var now = { x:event.target.x, y:event.target.y, z:event.target.z };
  values.push(now);
  
  // Cloud-based Deployment
  if(cloudBtnActivated && values.length > 1) {
    mqttClient.pub(createJsonString(values), topic);
    values.shift();
  }

  // Edge-based Deployment
  else if(edgeBtnActivated && values.length > 1) {
    var check = isStanding(now);
    if(check)
      setMeasureText('x: ' + event.target.x + '
y: ' + event.target.y + '
z: ' + event.target.z + "
You're standing");
    else
      setMeasureText('x: ' + event.target.x + '
y: ' + event.target.y + '
z: ' + event.target.z + "
You're moving");
    mqttClient.pub(createJsonString(check), topic);
  }
}

為了停止讀取,我編寫了一個(gè)簡(jiǎn)單的函數(shù),它不會(huì)消除傳感器對(duì)象(請(qǐng)記住 start 函數(shù)),但會(huì)清理專用于顯示 HAR 結(jié)果的區(qū)域。

function stop() {
  if(accelerometer != null)
    accelerometer.stop();
  setMeasureText("");
}

好吧,讓我們看看HAR 模型中最期待的部分代碼。實(shí)際上,您在編寫 Lambda 函數(shù)時(shí)已經(jīng)看到了它,但我沒(méi)有說(shuō)任何關(guān)于它的內(nèi)容。它是如何工作的?它對(duì)兩個(gè)連續(xù)的措施進(jìn)行簡(jiǎn)單檢查,以檢測(cè)用戶是否在移動(dòng)。如果移動(dòng)超過(guò)指定閾值,則結(jié)果是移動(dòng),否則不是。閾值和歸一化因子是根據(jù)經(jīng)驗(yàn)計(jì)算的,以盡量減少噪聲,結(jié)果非常好。

// Check if the user is standing (do side effect on values array removing the old element)
function isStanding(now) {
  var before = values.shift();
  // One decides for all
  if((Math.abs(now.x - before.x)*0.67 > 0.292)
     || (Math.abs(now.y - before.y)*0.7 > 0.145)
     || (Math.abs(now.z - before.z)*0.67 > 0.45))
        return false;
  return true;
}

最后但同樣重要的是,要查看最后一小時(shí)的活動(dòng)(如果啟用了云計(jì)算,還有傳感器值),您可以單擊顯示最后一小時(shí)的值,該值將對(duì)數(shù)據(jù)庫(kù)執(zhí)行查詢以檢索數(shù)據(jù),然后通過(guò)可縮放和可平移的圖表正確顯示它們。這些是使用Chart.js庫(kù)實(shí)現(xiàn)的,Hammer.js用于手勢(shì)識(shí)別,chartjs-plugin-zoom用于縮放和平移。

與 DynamoDB的連接是通過(guò)如下修改之前的憑證塊來(lái)執(zhí)行的

var uuid       = createUUID();
var mqttClient = null;

// Initialize Amazon Cognito credentials provider
AWS.config.region      = '';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: '',
});

// Obtain credentials
AWS.config.credentials.get(function(){
  // Credentials will be available when this function is called
  var host       = "";
  var requestUrl = SigV4Utils.getSignedUrl(host, AWS.config.region, AWS.config.credentials);
  mqttClient     = new PahoMQTTClient(requestUrl, uuid);
  mqttClient.conn(callbackConnection, callbackReceive);
});

var docClient = new AWS.DynamoDB.DocumentClient();

由于 DynamoDB 是NoSQL數(shù)據(jù)庫(kù),因此您必須使用以下語(yǔ)法

var params = {
  TableName : "",
  ProjectionExpression: ", ..., ",
  KeyConditionExpression: "",
  FilterExpression: "",
  ExpressionAttributeNames:{
    "": "",
    ...,
    "": ""
  },
  ExpressionAttributeValues: {
    "": "",
    ...,
    "": ""
  }
};

在哪里:

  • KeyConditionExpression指定搜索條件:確定要從表或索引中讀取的項(xiàng)目的字符串。您必須將分區(qū)鍵名稱和值指定為相等條件
  • FilterExpression確定應(yīng)將查詢結(jié)果中的哪些項(xiàng)目返回給您
  • ExpressionAttributeNames提供名稱替換。這是因?yàn)樵?Amazon DynamoDB 中保留了一些單詞
  • ExpressionAttributeValues提供值替換。這是因?yàn)槟悴荒茉谌魏伪磉_(dá)式中使用文字,包括 KeyConditionExpression
  • N >= M 和 N >= L

有關(guān)更多詳細(xì)信息,請(qǐng)參閱AWS DynamoDB 文檔。

因此,為了滿足該特征,查詢?nèi)缦?/font>

var params = {
  TableName : "",
  ProjectionExpression: cloudBtnActivated ? "Id, #dt, x, y, z, isStanding" : "Id, #dt, isStanding",
  KeyConditionExpression: "Id = :clientID and #dt between :start_h and :end_h",
  FilterExpression: "computation = :computation",
  ExpressionAttributeNames:{
    "#dt": "dateTime"
  },
  ExpressionAttributeValues: {
    ":clientID": uuid,
    ":start_h":  dateTime[1],
    ":end_h":    dateTime[0],
    ":computation": cloudBtnActivated ? "cloud" : "edge"
  }
};

docClient.query(params, function(err, data) {
  if (err) {
    // Error
  } else {
    // Success, do stuff
  }
});

其中cloudBtnActivated是一個(gè)全局標(biāo)志,用于表示云計(jì)算按鈕是否被激活。將功能分開(kāi)就足夠了,因?yàn)樗鼈兪腔コ獾模茨荒芡瑫r(shí)使用兩者)。

警告:我使用Id作為分區(qū)鍵,而作為排序鍵dateTime ,它們必須與您在 DynamoDB 表中定義的一致。因此,如果您使用不同的密鑰,請(qǐng)?jiān)诖a中將我的密鑰替換為您的密鑰。

如果成功,您必須迭代響應(yīng)對(duì)象以檢索數(shù)據(jù)并顯示它們

var sensorValues = [];
var dateTimes = [];

// Additional arrays for cloud computing
var xValues = [];
var yValues = [];
var zValues = [];

// Check if cloud computing
if(cloudBtnActivated)
  data.Items.forEach(function(data) {
    sensorValues.push(data.isStanding ? 0 : 1);
    // DynamoDB does not support float type so, in the table, the value is stored as string
    xValues.push(parseFloat(data.x));
    yValues.push(parseFloat(data.y));
    zValues.push(parseFloat(data.z));
    dateTimes.push(data.dateTime);
  });

else
  data.Items.forEach(function(data) {
    sensorValues.push(data.isStanding ? 0 : 1);
    dateTimes.push(data.dateTime);
  });

// Continue scanning if we have more data (per scan 1MB limitation)
if (typeof data.LastEvaluatedKey != "undefined") {
  params.ExclusiveStartKey = data.LastEvaluatedKey;
  docClient.scan(params, onScan);
}

if (sensorValues.length == 0)
  setTimeout(function() {
  alert("No data sent in the past hour");
  }, 100);

else {
  if(cloudBtnActivated) {
    drawLineChart(dateTimes, sensorValues, "historyCanvas", "Activity Cloud Computing");
    drawLineChart(dateTimes, xValues, "historyXCanvas", "x Cloud Computing");
    drawLineChart(dateTimes, yValues, "historyYCanvas", "y Cloud Computing");
    drawLineChart(dateTimes, zValues, "historyZCanvas", "z Cloud Computing");
  }
  else
    drawLineChart(dateTimes, sensorValues, "historyCanvas", "Activity Edge Computing");
}

有關(guān)非重點(diǎn)代碼的更多詳細(xì)信息,請(qǐng)參閱我的GitHub 存儲(chǔ)庫(kù)

就是這樣,享受它,如果您欣賞我的工作,請(qǐng)通過(guò)喜歡或評(píng)論告訴我。謝謝!


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開(kāi)發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開(kāi)關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德?tīng)栔?/a>
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)