Thanapon Tapala

Backend Developer

Embedded Developer

Smart Farmer

Maker

Thanapon Tapala

Backend Developer

Embedded Developer

Smart Farmer

Maker

Blog Post

[AWS-IoT] Device Provisioning สำหรับสเกลอุปกรณ์หลายๆตัว ภาค Hardware บ้าง

July 28, 2022 Arduino, AWS, ESP32, MQTT, PlatformIO
[AWS-IoT] Device Provisioning สำหรับสเกลอุปกรณ์หลายๆตัว ภาค Hardware บ้าง

สวัสดีครับ มาต่อจาก Blog ก่อนหน้านี้ที่ปล่อยลอยไว้นานหลายเดือนเลย หากใครจำไม่ได้แล้วว่า เอ๊ะ! ทำอะไรไปบ้างเนี้ยแนะนำให้ย้อนกลับไปดูได้นะครับ

[AWS-IoT] Device Provisioning สำหรับสเกลอุปกรณ์หลายๆตัว-1

Device Provision ภาคแรกเป็นการ Config AWS IoT Core ให้พร้อมสำหรับการ Scale อุปกรณ์หลายๆตัว

ส่วนใครยังไม่เข้าใจ Sequence diagram ของ การ Provisioning ลองกลับไปอ่านดูนะครับใน Blog นี้ ผมจะอธิบายโค๊ดแบบ คร่าวๆให้ฟังนะครับ

เริ่มกันเลยดีกว่า

ด้านล่างนี้จะเป็นโค๊ดลองไป Clone ลงมาเล่นกันได้นะครับ

toygame/aws-iot-device-provisioning-esp32

AWS IoT device provisioning with Fleet provisioning templates, The hardware is ESP32 that built-in a WiFi and Bluetooth module.

Clone repo ลงมาในเครื่องแล้วอย่าลืมเปลี่ยนส่วนของ Configuration นะครับจะมี WiFi SSID/Password กับ AWS IoT Endpoint อีกอย่างที่ขาดไม่ได้คือ Claim Certificate ให้เราไปอัพเดทในโฟลเดอร์ certs ด้วย

#define WIFI_SSID "xxxxxxx"
#define WIFI_PASSWORD "xxxxxxxx"
#define AWS_IOT_ENDPOINT "xxxxxxx.iot.ap-southeast-1.amazonaws.com"

ลอง Upload ดูนะครับผมเขียน Makefile ไว้ให้ แต่ก่อนใช้งานจำเป็นต้องลง PlatformIO CLI ก่อนน้าา เดี๋ยวแตก!!! วิธีใช้ Makefile ก็

make

หลังจากที่ตัวโค๊ด อัพโหลดเสร็จแล้วเราจะเห็นว่ามันจะพยายามเชื่อมต่อไปที่ WiFi Router ของเราก่อน จากนั้นมันจะเข้าไปทำการ Provisioning ตัวเองต่อเลย จนเสร็จแล้วก็จะได้ข้อความ “Register things successfully” ตามภาพปลากรอบ

Restart เสร็จแล้ว สเต็ปต่อไปอุปกรณ์จะเข้าไปอ่าน ไฟล์ aws.json ที่เราเก็บไว้ใน FS เพื่อเข้าไปอ่าน Device Certificate กับ Private Key ที่ถูกเก็บไว้ เพื่อเอามาใช้สำหรับเชื่อมต่อไปยัง AWS IoT Core ซึ่งมันใช้การ Authen แบบ X.509 Certificate

ลองเช็คดูว่ามีชื่ออุปกรณ์ของเราใช้ AWS IoT Console ไหม ถ้ามีก็ถือว่าผ่าน คุณได้ไปต่อ!!!!

ทดสอบ Publish MQTT ลงมาที่อุปกรณ์หน่อยสิ

Okay สามารถรับ MQTT Packet จาก AWS IoT Core ได้!!!

อธิบาย Coding สักนิดละกัน

  • หลังจากเสียบสายไฟเข้าอุปกรณ์ปุ๊ป มันก็จะทำพยายามเชื่อมต่อเข้าไป WiFi Router ของเราก่อนอันนี้ก็ไม่มีอะไร basicๆ ครับ
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi..");
while (WiFi.status() != WL_CONNECTED)
{
  delay(1000);
  Serial.print(".");
}
Serial.println("Connected.");
  • จากนั้นจะเริ่มเปิดไฟล์ aws.json ที่อยู่ใน Filesystem เสร็จแล้วเราก็ได้จะได้ instance ของ File ออกมา
if (!SPIFFS.begin(true))
{
  Serial.println("An Error has occurred while mounting SPIFFS");
  return;
}
// Read AWS config file.
File file = SPIFFS.open("/aws.json", "r");
if (!file)
{
  Serial.println("Failed to open file for reading");
  return;
}
  • เมื่อได้ข้อมูลใน File ออกมาแล้วก็ Parse มันออกมาให้อยู่ในรูป JSON เพื่อให้ง่ายต่อการอ่านกับการใช้งาน
  • เสร็จแล้วก็เช็คเงื่อนไข ถ้า JSON มี Key ที่ชื่อ certificatePem ก็ให้มันเชื่อมต่อไปยัง AWS IoT Core ได้เลยส่วนถ้าไม่เจอก็ไล่ให้มันไป Provisioning
DynamicJsonDocument cert(4000);
auto deserializeError = deserializeJson(cert, file);
if (!deserializeError)
{
  if (cert["certificatePem"])
  {
    connectToAWS(cert);
  }
}
else
{
  createCertificate();
}
file.close();

ขั้นตอนการ Provisioning

  • ใช้ Claim certificate ในการเชื่อมต่อไปที่ AWS IoT Core ก่อน
net.setCACert(AWS_CERT_CA);
net.setCertificate(AWS_CERT_CRT);
net.setPrivateKey(AWS_CERT_PRIVATE);
client.setServer(AWS_IOT_ENDPOINT, 8883);
// Create a message handler
client.setCallback(messageHandler);
// Set buffer size for receive a certificate.
client.setBufferSize(4000);
Serial.print("Connecting to AWS IOT.");
client.connect(THING_GROUP);
  • Subscription MQTT Topic สำหรับรับ Response พวก certificate กลับมา สุดท้ายก็ทำการ Publish Payload ว่างๆ ไปยัง Topic “$aws/certificates/create/json” เพื่อบอกว่าเราจะ Provision อุปกรณ์แล้วนะก็เป็นอันจบ
  client.subscribe("$aws/certificates/create/json/accepted");
  client.subscribe("$aws/certificates/create/json/rejected");
  client.subscribe("$aws/provisioning-templates/esp32_fleet_prov_template/provision/json/accepted");
  client.subscribe("$aws/provisioning-templates/esp32_fleet_prov_template/provision/json/rejected");
  Serial.println("Create certificate..");
  client.publish("$aws/certificates/create/json", "");

Handle MQTT Payload กันบ้าง

  • ถ้า Topic “$aws/certificates/create/json/accepted” เราก็โยนเข้าไปที่ Function saveCertificateToFS กับ registerThing

saveCertificateToFS: ตัว Function นี้จะทำการบันทึก certificatePem กับ privateKey ลงใน Filesystem

registerThing: จะ Publish ไปที่ Topic “$aws/provisioning-templates/esp32_fleet_prov_template/provision/json” ซึ่ง Payload ที่จะส่งไปจะมี certificateOwnershipToken กับ parameters SerialNumber ไปด้วยเพื่อใช้เป็นชื่อของอุปกรณ์

  • ส่วนถ้าเป็น Topic “$aws/provisioning-templates/esp32_fleet_prov_template/provision/json/accepted” ก็แสดงว่า AWS IoT Core register อุปกรณ์เราเรียบร้อยแล้ว ทีนี่เราก็สามารถใช้ Certificate ตัวใหม่ได้เลย
DynamicJsonDocument doc(length);
deserializeJson(doc, payload);
if (topic == "$aws/certificates/create/json/accepted")
{
  saveCertificateToFS(doc);
  registerThing(doc);
}
else if (topic == "$aws/provisioning-templates/esp32_fleet_prov_template/provision/json/accepted")
{
  Serial.println("Register things successfully.");
  Serial.println("Restart in 5s.");
  sleep(5);
  ESP.restart();
}

เป็นยังไงกันบ้างครับสำหรับการ Scale อุปกรณ์หลายๆตัว ถ้าให้มานั่ง Generate Certificate ทุกครั้งคงจะเป็นอะไรที่ลำบากมากๆกันเลยทีเดียว ยิ่งถ้าคิดถึงว่าจะ Scale อุปกรณ์สัก 1000 ตัวแล้วน่าจะใช้เวลาพอสมควรกันเลย 5555+ หวังว่าการใช้ Device Provisioning แบบ Claim Certificate จะช่วยท่านได้บ้างนะครับ ตอนหน้าถ้ามีเวลาเดี๋ยวมานั่งเขียนว่าเราจะ Provision ผ่าน Greengrass[Edge] กันยังไงดี ซึ่งผมใช้วิธี Provisioning by trusted user แทน สำหรับวันนี้ขอบคุณและสวัสดีครับ

Twelve companies to embed AWS Greengrass - Enterprise IoT Insights

Taggs: