巧用 Soracom Beam 和 Amazon SageMaker 來預測 M5Stack 的電力需求

今天,我想分享一個令人興奮的新整合,它在科技界掀起了波瀾。我說的是將 Amazon SageMaker 與 Soracom Beam 整合在一起,後者是一種資料傳輸服務,現在與 AWS Signature V4 相容。

透過 Amazon SageMaker 和 Soracom Beam 的集成,您不再需要擔心在裝置上管理身分驗證資訊和 SigV4 產生邏輯。這使得您的裝置可以在沒有 aws 憑證的情況下向 Amazon SageMaker 發送數據,並將 AI 功能整合到您的裝置中。 例如,您可以使用 Amazon SageMaker 端點輕鬆預測一些統計資料。

這篇貼文將重點放在的就是後一種功能。之後,我們將仔細研究微控制器 M5Stack 如何與 Amazon SageMaker 整合。 那麼,就讓我們開始吧!

架構概述

我們先來看一下系統架構。
M5Stack 透過 Soracom Beam 向 Amazon SageMaker 發送資料。在此步驟中,Soracom Beam 將接收未使用 TLS 加密的 HTTP 流量,並將其轉送給使用 TLS 加密的 Amazon SageMaker。Soracom Beam將在對 Amazon SageMaker 的請求中新增 SigV4 身份驗標頭。

image

接下來,我將向大家展示下面的硬體架構。

M5Stack 透過 ENVⅢ 感測器捕捉濕度,溫度和壓力,並透過 3G 擴充板將資料傳送到 Soracom Beam。

image

如何設定環境

那現在就讓我們來創建你的環境吧!

建立人工智慧模型與Amazon SageMaker

透過配置,從蜂窩設備到 Soracom Beam http://beam.soracom.io:18080/ 的 HTTP 流量被轉發到Amazon SageMaker 端點,例如 https://runtime.sagemaker.us-west-2.amazonaws.com/ ,並附有 AWS 身份驗標頭。

:warning:在本例中,該模型基於 2022 年 12 月的真實數據,針對東京的天氣狀況進行了最佳化。根據你的氣候環境,你的預測可能會得到較低的準確性。

image

配置M5 Stack

  1. 請在 Arduino IDE 中安裝以下軟體。
  1. 建立一個新的草圖並將其安裝在 M5Stack 中
#include <M5Stack.h>

//Libraries for cellular connectivity
#define TINY_GSM_MODEM_UBLOX
#include <TinyGsmClient.h>
#include <HTTPClient.h>
#include <ArduinoHttpClient.h>

//Libraries for sensor
#include "UNIT_ENV.h"

TinyGsm modem(Serial2); 
TinyGsmClient ctx(modem);

const char* beamServerAddress = "beam.soracom.io";
const int beamPort = 18080;
const String powerModelName = "sagemaker-xgboost-2023-02-28-00-54-23-394";

const char* clockServerAddress = "worldtimeapi.org";
const int clockServerPort = 80;
const String datetime_prefix = "datetime: ";
  
SHT3X sht30;
QMP6988 qmp6988;


void setup() {

  //Initialization
  M5.begin();
  M5.lcd.setTextSize(2);
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.println("M5Stack Now Powered On");

  //Initializing the modem and configure APN
  M5.Lcd.print("Restarting Modem...");
  Serial2.begin(115200, SERIAL_8N1, 16, 17);
  modem.restart();
  M5.Lcd.println("Done.");

  M5.Lcd.print("Modem Info:");
  String modemInfo = modem.getModemInfo();
  M5.Lcd.println(modemInfo);

  M5.Lcd.print("Waiting to be registered..");
  while (!modem.waitForNetwork()) M5.Lcd.print(".");
  M5.Lcd.println("done.");

  M5.Lcd.print("Creating PDP context with APN soracom.io..");
  modem.gprsConnect("soracom.io", "sora", "sora");
  M5.Lcd.println("done.");

  M5.Lcd.print("Connecting to the network..");
  while (!modem.isNetworkConnected()) M5.Lcd.print(".");
  M5.Lcd.println("done.");

  M5.Lcd.print("My IP addr:");
  IPAddress ipaddr = modem.localIP();
  M5.Lcd.print(ipaddr);
  
  //Initializing the sensor
  Wire.begin(); 
  qmp6988.init();

  
  delay(2000);
  
}

void loop() {

  //1.Get hour
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(WHITE);
  
  String datetime = get_datetime();
  
  int currentHour = datetime.substring(11,13).toInt();  
  
  //2.Get temperature and humidity
  float tmp = 0.0; // temperature
  float hum = 0.0; // humidity
  
  if(sht30.get()==0){ 
    tmp = sht30.cTemp; 
    hum = sht30.humidity; 
  }
  M5.Lcd.printf("Hour: %d Temp: %2.1f Humi: %2.0f%%  \r\n", currentHour, tmp, hum);

  
  M5.Lcd.printf("Predicting power demand.. ");
  HttpClient client = HttpClient(ctx, beamServerAddress, beamPort);

  //3.Inference power demand for the next hour based
  String contentType = "text/csv";
  String body = String(currentHour) + ","  + String(tmp) + ","  + String(hum);
  int err = client.post("/endpoints/" + powerModelName + "/invocations", contentType, body);

  //Check if the request is succeeded
   if (err != 0) {
    M5.Lcd.println("failed.");
    return;
  }
  M5.Lcd.println("done.");

  // Read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();

  M5.Lcd.printf("Power Demand: ");
  M5.Lcd.println(response);
              
  delay(5000);
  
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.println("Retrying now...");

}


//Get time info
String get_datetime()
{
  M5.Lcd.printf("Get current time..");

  HttpClient client = HttpClient(ctx, clockServerAddress, clockServerPort);

  int err = client.get("/api/timezone/Asia/Tokyo.txt");

  //Check if the request is succeeded
   if (err != 0) {
    M5.Lcd.println("failed.");
    return "";
  }
  
  String response = client.responseBody();

  int start = response.indexOf(datetime_prefix);
  int end = response.indexOf('\n', start);
  String datetime = response.substring(start + datetime_prefix.length(), end);
  M5.Lcd.println("done.");
  return datetime;
  
}

我將在草圖中解釋 loop() 方法中發生了什麼。

  1. WorldTimeAPI 取得當前時間,並在 24 小時內提取小時。

  2. 使用溫濕度空氣壓力感測器(SHT30+QMP6988)的ENV III單元取得溫度 [℃] 和濕度 [%]。

  3. 推斷下一小時的電力需求:透過 Soracom Beam 將小時、溫度和濕度發送到 Amazon SageMaker,以預測下一小時的電力需求。請注意,透過 Soracom Beam 呼叫 Amazon SageMake r不需要 aws 憑證,因為 Soracom Beam 添加了其身份驗標頭。

正式運行

現在我們來開動吧!

你會得到如下圖的預測結果。我在2023年2月進行了測試,溫度為 24.2,濕度為 37%,時間是下午 3 點,然後預測的電力需求約為 2873.53 / 10000 千瓦。

image