Microsoft Azure IoT Hub(2)
從Android裝置傳送訊息至IoT Hub
- IoT Hub 建立新device
1. 進入上一章建立的IoT Hub(IoTWorkSuccess) 點選 "IoT 裝置"
2. 點選 "新增" 進入 "建立裝置"
3. 在"裝置識別碼" 輸入 "andrid_device01"
4. 在"驗證類型" 選取"對稱金鑰"(原預設不動)
5. 在"自動產生金鑰" 選取"啟動" (原預設不動)
6. 按下"儲存", 完成新增
7. 點選新建立的"android_device01"裝置, 進入 "andrid_device01" 頁面
8. 點選"主要連接字串"後面"顯示/隱藏欄位內容" 可以顯示出此device的連線字符串
9. 點選 "copy" 待coding時使用此字串
B. 輸入下列資料 Name : DeviceToIoT Package Name: com.rdwatchworld.devicetoiot, Save Location: E:\worksapces\Azure\DeviceToIoT 後按下 "Finish"
2. Layout設定: 佈置一個"Multiline Text"及"Button":
A. 從"Android"切換至"Project"後展開以下目錄"DeviceToIoT", "app", "src", "main", "res", "layout"B. 開啟"activity_main.xml",刪除原有的"TextView:,拖拉一個"Multiline Text"拉至適當大小再拖一個"Button放至下方, 分別id設為 "Info_Text"與"Send_Button"
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:layout_editor_absoluteX="123dp"
tools:layout_editor_absoluteY="1dp"
tools:ignore="MissingConstraints">
<EditText
android:id="@+id/Info_Text"
android:layout_width="351dp"
android:layout_height="101dp"
android:ems="10"
android:gravity="start|top"
android:inputType="textMultiLine"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="42dp"
tools:layout_editor_absoluteY="30dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/Send_Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start"
tools:layout_editor_absoluteX="85dp"
tools:layout_editor_absoluteY="166dp"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
tools:layout_editor_absoluteX="234dp"
tools:layout_editor_absoluteY="166dp"
tools:ignore="MissingConstraints" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
3. Android Studio Project設定(build.gradle):
D. 在"Step 2" 選擇"Implementation"後按下"OK", 再按一次"OK".
api ('com.microsoft.azure.sdk.iot:iot-device-client:1.28.0') {
exclude module: 'slf4j-api'
}
4. 加入Android 權限(AndroidManifest.xml)
A. 加入<uses-permission android:name="android.permission.INTERNET" />
5. 撰寫程式碼:
B, 在onCreate Function中將之前佈置的Info_Text及Send_Button分別建立mInfo與mSend二件物件
C. 將mSend建立OnClickListener以對應button事件
D. 程式碼如下:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText mInfo = (EditText)findViewById(R.id.Info_Text);
Button mSend = (Button)findViewById(R.id.Send_Button);
mSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
E. 撰寫連線雲端需要的定義:
a. 連接字串: private final String connString = "HostName=IotWorkSuccess.azure-devices.net;DeviceId=android_device01;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
b. 連接Device ID: private final String deviceId = "andrid_device01";
c. 連線的protocol: private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
d. 定義雲端Device Client端物件: private static DeviceClient client;
F. 建立一個Thread來無限發送Message(隨機產生的溫度溼度值)至IoT Hub:
private static class MessageSender implements Runnable {
try {
// Initialize the simulated telemetry.
double minTemperature = 20; //最小的溫度值
double minHumidity = 60; //最大的溼度值
Random rand = new Random(); //建立一個隨機產生的值的rand物件
while (true) { //無限迴圈
// Simulate telemetry.
double currentTemperature = minTemperature + rand.nextDouble() * 15;
double currentHumidity = minHumidity + rand.nextDouble() * 20;
TelemetryDataPoint telemetryDataPoint = new TelemetryDataPoint();
telemetryDataPoint.temperature = currentTemperature;//產生的隨機溫度
telemetryDataPoint.humidity = currentHumidity; //產生的隨機溼度
// Add the telemetry to the message body as JSON.
String msgStr = telemetryDataPoint.serialize();
Message msg = new Message(msgStr); //Message是com.microsoft.azure.sdk.iot.device內的Message物件
// Add a custom application property to the message.
// An IoT hub can filter on these properties without access to the message body.
msg.setProperty("temperatureAlert", (currentTemperature > 30) ? "true" : "false"); //超過30度就列為警示
System.out.println("Sending message: " + msgStr);
// Send the message.
EventCallback callback = new EventCallback();
client.sendEventAsync(msg, callback, 1);//將msg送至雲端, response 到EvenCallback
mInfo.setText("Temperature = "+ currentTemperature + " Humidity = " + currentHumidity + "\n");將溫度及溼度秀在Edit Text中
Thread.sleep(5000);//停5秒再繼續}} catch (InterruptedException e) {System.out.println("Finished.");}
}
}
G. 建立EventCallback來收取傳送Message後雲端傳回來的事件
private static class EventCallback implements IotHubEventCallback {
public void execute(IotHubStatusCode status, Object context) {
System.out.println("IoT Hub responded to message with status: " + status.name());
if (context != null) {
synchronized (context) {
context.notify();
}
}
}
} H. 在Button 的onClick事件中建立Thread來發送Message到雲端
public void onClick(View view) {
MessageSender sender = new MessageSender(); //步驟F所建立的MessageSender Thread
executor = Executors.newFixedThreadPool(1);
executor.execute(sender);//執行MessageSender Thread
}
I. 離開時記得釋出物件:
public void onDestroy() {
super.onDestroy();
try {
executor.shutdownNow();//Thread停止
client.closeNow();//關閉雲端連線
} catch (IOException e) {
e.printStackTrace();
}
}
J. 驗證雲端是否收到Message:
- 建立雲端儲存體來存放message
- 在搜尋列輸入"儲存體帳戶", 進入儲存體帳戶頁面
- 按下"新增"進入建立儲存體帳戶頁面
- 在"資源群組"選擇之前建立的"WorkSuccessRG"
- 在"儲存體帳戶名稱"輸入"storageworksuccess"(只能小寫)
- 在"位置"選擇"東南亞"(跟 WorkSuccessRG同一區會比較好)
- 其餘設定保持預設不變按下"檢閱+建立" 後再按下"建立"等待完成
- 開啟cloud shell來下command, 如開啟時需選擇一儲存體請選擇"storageworksuccess"
- 在command下輸入az iot hub monitor-events --hub-name IotWorkSuccess --device-id android_device01按下enter即可看到傳來的Message













