Xây dựng hệ thống Internet of Things sử dụng nền tảng AWS IoTs (P2)

Như đã giới thiệu ở phần 1, các thiết bị sau khi đăng ký với AWS IoT được đại diện bởi các “Things”. Trong phần này chúng ta sẽ tìm hiểu về cách quản lý trạng thái của thiết bị, được biểu thị thông qua một tính năng có tên là Device Shadow (hay Thing Shadow), qua đó chúng ta có thể thực hiện các truy vấn như cập nhật, truy xuất, xóa,… để tương tác với các ứng dụng khác theo thời gian thực.

Phần 2: Tương tác với Device Shadow Service sử dụng giao thức MQTT

Device Shadow về cơ bản là một “JSON State Document”, có thể hiểu đơn giản Device Shadow giống như một cơ sở dữ liệu trung gian dùng để lưu trữ trạng thái của thiết bị được đại diện bởi Thing, theo định dạng chuỗi JSON và có kiến trúc, quy tắc đã được xây dựng sẵn bởi AWS. Chúng ta có thể tương tác với shadow của thiết bị bằng cách sử dụng giao thức MQTT hoặc REST API. Trong bài viết này mình sẽ giới thiệu với các bạn về kiến trúc của Device Shadow và cách thức tương tác sử dụng giao thức MQTT. Để tiếp thu tốt hơn khi đọc bài viết này, các bạn nên trang bị một chút kiến thức về giao thức MQTT (một loại giao thức theo mô hình publish, subscribe) và chuỗi JSON (một định dạng chuyển đổi dữ liệu, sử dụng các cặp key-value để dễ dàng đọc và ghi), những kiến thức này không quá khó và rất phổ biến nên các bạn có thể dễ dàng tìm đọc trên internet nhé.

Dữ liệu lưu trữ trong Device Shadow đại diện cho trạng thái của thiết bị, AWS IoT chia thành 2 loại trạng thái để lưu trữ là: trạng thái thực của thiết bị trạng thái mong muốn của thiết bị và 2 đối tượng tương tác chủ đạo là thiết bị (device) và các ứng dụng (application).

  • Trạng thái thực của thiết bị: là trạng thái hiện tại của thiết bị vật lý mà Device Shadow đang mô tả, được lưu trữ trong trường reported của chuỗi JSON. Vì vậy, chỉ có các thiết bị vật lý truy vấn vào trường reported và các ứng dụng khác sẽ dựa vào giá trị ở trường này để truy xuất trạng thái của thiết bị theo thời gian thực mà không sợ bị xung đột hoặc nhầm lẫn.
  • Trạng thái mong muốn của thiết bị: là trạng thái mà các ứng dụng khác mong muốn gửi đến thiết bị, ví dụ dữ liệu từ các ứng dụng điều khiển từ xa bằng điện thoại, website, trợ lý ảo,… Loại dữ liệu này sẽ được lưu trữ riêng ở trường desired của chuỗi JSON. Thiết bị vật lý sẽ dựa vào giá trị ở trường này để thay đổi trạng thái mới và sau đó cập nhật vào trường reported.

Cả 2 trường reporteddesired sẽ nằm bên trong trường state. Như vậy, nhìn chung dữ liệu trong Device Shadow của chúng ta sẽ có định dạng theo chuỗi JSON như sau:

Ngoài state ra, Device Shadow còn có thể chứa các trường như metadata, timestamp, clientToken, version,… để thể hiện các thông tin cụ thể khác nhau về thời gian, phiên bản,… của Device Shadow, giúp việc quản lý và xác thực dễ dàng hơn. Các trường này sẽ được tự động quản lý bởi AWS, nhiệm vụ chính của chúng ta là tập trung thiết kế hệ thống chỉ cần quan tâm đến trường state (bao gồm repored desired).

Device Shadow sử dụng các MQTT topic được định nghĩa sẵn giúp các ứng dụng và thiết bị có thể tương tác với nhau dễ dàng hơn bằng cách subscribe hoặc publish vào các topic này, cụ thể các ứng dụng có thể thực hiện các tương tác với thiết bị liên quan đến 3 loại truy vấn đối với reported và desired là: UPDATE (cập nhật dữ liệu), GET (truy xuất dữ liệu) hoặc DELETE (xóa dữ liệu). Để thực hiện thành công các yêu cầu truy vấn trên, thiết bị và các ứng dụng phải publish hoặc subscribe đúng tên topic và đúng định dạng gói tin được quy định bởi AWS IoT nếu không thì yêu cầu đó sẽ bị rejected (tức là bị từ chối). Để thực hiện truy vấn, chúng ta sẽ publish dữ liệu vào các topic có định dạng sau:  $aws/things/thingName/shadow/queryType

Trong đó: thingName là tên của Thing đã tạo đại diện cho thiết bị và queryType là loại truy vấn muốn thực hiện (bao gồm update, get hoặc delete).

Sau khi thực hiện truy vấn, AWS sẽ lặp tức phản hồi lại bằng cách tự động publish một gói tin đến topic tương ứng có dạng: $aws/things/thingName/shadow/queryType/Response

Trong đó: Response là loại phản hồi (bao gồm accepted hoặc rejected đối với cả 3 loại truy vấn và có thể có thêm delta, documents đối với truy vấn update). Vì đây là các topic được AWS sử dụng để phản hồi lại yêu cầu truy vấn nên chúng ta chỉ được phép subscribe chứ không được publish dữ liệu đến các topic Response này.

Cụ thể danh sách các topic Response gồm có:

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi một truy vấn UPDATE được thực hiện thành công.

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi một truy vấn UPDATE bị từ chối.

$aws/things/thingName/shadow/update/documents

Device Shadow Service sẽ tự động publish gói tin đến topic này khi một truy vấn UPDATE được thực hiện thành công. Tương tự như update/accepted nhưng dữ liệu được publish đến topic này khác ở chỗ là sẽ chia thành 2 trường: previouscurrent chứa dữ liệu trước và sau khi cập nhật.

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi có sự sai khác được phát hiện giữa reported và desired của Device Shadow.

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi có một truy vấn GET đến Device Shadow được thực hiện thành công.

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi có một truy vấn GET đến Devive Shadow bị từ chối.

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi một truy vấn DELETE được thực hiện thành công

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

Device Shadow Service sẽ tự động publish gói tin đến topic này khi một truy vấn DELETE bị từ chối.

Bây giờ mình sẽ sử dụng một ví dụ để minh họa quá trình giao tiếp giữa một thiết bịcác ứng dụng A, B C với dịch vụ Device Shadow. Ví dụ này mình sẽ sử dụng Device Shadow để quản lý một bóng đèn có kết nối internet tên là Light được đại diện bởi Thing có tên là TapitLight. Nếu các bạn chưa biết cách tạo Thing thì có thể xem lại phần 1. Các bạn có thể sử dụng trình mô phỏng MQTT Client của AWS ở cửa sổ console để thực hiện publish, subscribe nhằm mô phỏng vai trò của thiết bị và các ứng dụng A, B, C nhé.

1) Khi thiết bị Light được bật, tức là chuyển từ off sang on, thiết bị sẽ gửi trạng thái hiện tại đến Device Shadow Service bằng cách publish một gói tin đến topic $aws/things/TapitLight/shadow/update với yêu cầu cập nhật ở trường reported với nội dung như sau:

Vì gói tin hợp lệ, Device Shadow Service sẽ phản hồi bằng cách ngay lập tức publish một gói tin sau vào topic $aws/things/TapitLight/shadow/update/accepted:

 

2) Một ứng dụng A subscribe topic này sẽ ngay lập tức nhận được dữ liệu mới cập nhật từ thiết bị và có thể sử dụng dữ liệu này để thực hiện hiển thị, đồng bộ,… tùy ý.

Lưu ý: nếu đã subscribe mà không nhận được gói tin nào từ topic $aws/things/TapitLight/shadow/update/accepted thì hãy thử subscribe topic $aws/things/TapitLight/shadow/update/rejected để kiểm tra nhé, vì có thể gói tin bị sai format không hợp lệ nên đã được publish đến topic rejected.

Bên cạnh đó, Device shadow service cũng publish một gói tin vào topic $aws/things/TapitLight/shadow/update/documents với 2 trường là previouscurrent mô tả trạng thái của Device Shadow trước và sau khi cập nhật:

 

3) Mặt khác, nếu một ứng dụng B muốn kiểm tra trạng thái hiện tại của Light bất cứ khi nào thì có thể thực hiện truy vấn GET bằng cách publish một gói tin trống đến topic $aws/things/TapitLight/shadow/get. Device shadow service sẽ lập tức publish gói tin phản hồi vào topic $aws/things/TapitLight/shadow/get/accepted với nội dung như sau:

Vì vậy, ứng dụng B đó phải subscribe topic $aws/things/TapitLight/shadow/get/accepted để nhận phản hồi từ AWS IoT, sau đó tiến hành đọc dữ liệu trong trường reported để lấy giá trị trả về. Nếu truy vấn thất bại, AWS IoT sẽ publish gói tin đến topic $aws/things/TapitLight/shadow/get/rejected.

 

4) Một ứng dụng C  với chức năng điều khiển từ xa muốn thay đổi trạng thái của Light từ on sang off thì thực hiện mong muốn cập nhật bằng cách thay đổi trường desired, ứng dụng C publish một gói tin có nội dung như sau vào topic $aws/things/TapitLight/shadow/update:

Device Shadow Service sẽ lập tức phản hồi bằng cách publish một gói tin vào topic $aws/things/TapitLight/shadow/update/accepted

Và vì có sự sai khác dữ liệu của Light giữa desired và reported nên AWS cũng sẽ publish gói tin đến $aws/things/TapitLight/shadow/update/delta

Lưu ý rằng topic $aws/things/TapitLight/shadow/update/delta chỉ nhận được gói tin khi Device Shadow Service nhận ra sự khác biệt về trạng thái giữa reported và desired. Thiết bị phải subscribe topic này để bắt được mong muốn cập nhật trạng thái mới từ ứng dụng C ở trường desired sau đó thực hiện thay đổi trạng thái thiết bị và publish gói tin vào $aws/things/TapitLight/shadow/update để cập nhật trạng thái mới vào trường reported đồng thời xóa đi giá trị trong desired bằng cách publish giá trị null vào trường này. Nếu không xóa thuộc tính trong desired, trong một số trường hợp Device Shadow Service sẽ nhận ra sự khác biệt giữa desired và reported không mong muốn dẫn đến cập nhật sai trạng thái.

 

Tạm kết

Như vậy các ứng dụng A, B, C có thể tương tác với thiết bị Light thông qua “cơ sở dữ liệu trung gian” là Device Shadow của Light (chính là Thing TapitLight) bằng cách khai tác các truy vấn thích hợp đối với các trường reported desired thông qua giao thức MQTT để đảm bảo quá trình điều khiển, giám sát, đồng bộ trạng thái và tránh xung đột giữa các ứng dụng. Nhìn chung AWS IoT cung cấp kiến trúc quản lý này rất hữu ích, tuy nhiên các nhà phát triển và lập trình viên phải biết cách xây dựng, sử dụng linh hoạt các ngữ cảnh giữa thiết bị và các ứng dụng trong các trường hợp online lẫn offline để khai thác tối đa hiệu quả của kiến trúc này giúp hệ thống hoạt động tốt nhất có thể. Các phần sau nhóm TAPIT IoTs sẽ hướng dẫn các bạn các kiến thức nâng cao hơn nữa về AWS IoT, cũng cách kết nối thiết bị vật lý đến AWS IoT Core giúp xây dựng các ứng dụng thực tế thú vị khác, cùng theo dõi đón xem nhé.

Chúc các bạn thành công!

Xem tiếp Phần cuối:  Kết nối ESP32 Dev Kit và AWS IoT sử dụng giao thức MQTT
Xem thêm:  Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32

Nhóm TAPIT IoTs