環境:Windows 10, Windows 10 Iot Core, Raspberry Pi, Visual Studio 2015, Windows Azure Iot Suite
本文將介紹 使用 Raspberry Pi 2 /Windows IOT Core 讀取 DHT22 的溫、溼度資訊後,
再將這些資訊送到 Azure Iot Hub, 讓 Azure Iot Suite 的 Remote Monitoring System 也可以取得 Device 的資料。
在「Raspberry Pi 2 /Windows IOT Core 讀取 DHT22 的溫、濕度資訊」或其他幾篇文章中,
我們已經可以在 Raspberry Pi 上讀取到 Sensor 的資料。
再來我們就可以將這些資料送到 Cloud 上,才叫 IOT ... ^_^。
而 Microsoft 已經為我們準備好一個蠻完整的 Remote Monitoring System 讓我們可以來使用。
Azure IoT Suite - Remote Monitoring 系統,您可以從 www.azureiotsuite.com 建立,
或是從 Azure/azure-iot-remote-monitoring(github) download Source 建立在 local ,
詳細可以參考 Herman 大大寫的文章「快速建置物聯網系統: Azure IoT Suite - Remote Monitoring 簡介及客製化」。
以下筆者將一步步介紹,如何讓Device容易將資料送上Cloud,
1. 在 Azure Remote Monitoring System 的管理功能,新增自定的 Device,如下,
在第3步時,要將 Device Id, Hostname 及它的 Key ,先記錄下來,讓 Device 來使用。
剛新增完成的 Device 它的狀態為 Pending ,因為還沒有任何的 Device 來對應到它。如下,
2. 調整原有Raspberry Pi上的程式,加入送到 Azure IoT Suite - Remote Monitoring System 部份
2.1. App 的 Package.appxmanifest 設定中的 Capabilities 勾選 Internet(Client),如下,
2.2. 加入 Microsoft.Azure.Devices.Client 及 Newtonsoft.Json 這2個 NuGet Package,如下,
2.3. 加入 Device 啟動時,要送給 Azure Remote Monitoring System 要的訊息(StartDevices Method),如下,
// Azure IoT Suite - Remote Monitoring
private const string _deviceId = "{新增 Device 的 Id}"; //dht_tw_235
private const string _hostName = "{新增 Device 時的hostName}";
private const string _deviceKey = "{新增 Device 時的 Key}";
private string _deviceConnstring = string.Empty;
private DeviceClient _deviceClient = null;
// Azure IoT Suite - Remote Monitoring
/// <summary>
/// 將設備的詳細資料送給Cloud
/// </summary>
/// <returns></returns>
async Task StartDevices()
{
try {
_deviceConnstring = string.Format("HostName={0};DeviceId={1};SharedAccessKey={2}",
_hostName, _deviceId, _deviceKey);
_deviceClient = DeviceClient.CreateFromConnectionString(
_deviceConnstring, TransportType.Http1);
JObject device = new JObject();
JObject deviceProps = new JObject();
deviceProps.Add("DeviceID", _deviceId);
deviceProps.Add("HubEnabledState", 1);
deviceProps.Add("DeviceState", "normal");
deviceProps.Add("UpdatedTime", DateTime.UtcNow);
deviceProps.Add("Manufacturer", "655資訊");
deviceProps.Add("ModelNumber", "Raspberry Pi 2 B+");
deviceProps.Add("SerialNumber", "0521");
deviceProps.Add("FirmwareVersion", "10.0586");
deviceProps.Add("Platform", "Windows10 IoT Core");
deviceProps.Add("Processor", "ARM");
deviceProps.Add("Latitude", 25);
deviceProps.Add("Longitude", 121);
device.Add("DeviceProperties", deviceProps);
device.Add("Commands", new JArray());
device.Add("IsSimulatedDevice", 0);
device.Add("ObjectType", "DeviceInfo");
device.Add("Version", "1.0");
var messageString = JsonConvert.SerializeObject(device);
var message = new Message(Encoding.UTF8.GetBytes(messageString));
await _deviceClient.SendEventAsync(message);
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
}
}
2.4. 加入 每1.5秒讀到的溫、溼度資訊送到 Azure Iot Hub(SendTelemetryData Method),如下,
/// <summary>
/// 將讀取到的溫、濕度資訊送到 Azure IoT Suite
/// </summary>
/// <param name="temperature"></param>
/// <param name="humidity"></param>
async Task SendTelemetryData(float temperature, float humidity)
{
try
{
JObject deviceData = new JObject();
deviceData.Add("DeviceId", _deviceId);
deviceData.Add("Temperature", temperature);
deviceData.Add("Humidity", humidity);
var msgString = JsonConvert.SerializeObject(deviceData);
var msg = new Message(Encoding.UTF8.GetBytes(msgString));
await _deviceClient.SendEventAsync(msg);
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
}
}
3.再到 Web 系統,切到 Dashboard ,就可以看到我們送上去的溫、濕度資訊,如下,
最後有加入 Call Cloud 的程式如下,
public sealed partial class MainPage : Page
{
private GpioPin _pin = null;
private Dht22 _dht = null;
private DhtReading reading = new DhtReading();
private DispatcherTimer timer;
const int DATA_PIN = 4; //GPIO 4
private int _SuccessCount = 0;
private int _FailCount = 0;
//for led
private GpioPin _pinLED = null;
private int LED_PIN = 27; //GPIO 27
// Azure IoT Suite - Remote Monitoring
private const string _deviceId = "{新增 Device 的 Id}"; //dht_tw_235
private const string _hostName = "{新增 Device 時的hostName}";
private const string _deviceKey = "{新增 Device 時的 Key}";
private string _deviceConnstring = string.Empty;
private DeviceClient _deviceClient = null;
// Azure IoT Suite - Remote Monitoring
public MainPage()
{
this.InitializeComponent();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1500);
timer.Tick += Timer_Tick;
InitGPIO();
if (_pin != null)
{
_dht = new Dht22(_pin, GpioPinDriveMode.Input);
//啟動設備時,要將設備的詳細資料送給Cloud
StartDevices();
Task.Delay(1000);
//啟動設備時,要將設備的詳細資料送給Cloud
timer.Start();
}
}
private void InitGPIO()
{
GpioController gpio = GpioController.GetDefault();
if (gpio == null)
{
_pin = null;
lblLog.Text = "There is no GPIO controller on this device.";
return;
}
_pin = gpio.OpenPin(DATA_PIN, GpioSharingMode.Exclusive);
_pinLED = gpio.OpenPin(LED_PIN);
_pinLED.Write(GpioPinValue.High);
_pinLED.SetDriveMode(GpioPinDriveMode.Output);
}
private async void Timer_Tick(object sender, object e)
{
timer.Stop();
try
{
reading = await _dht.GetReadingAsync().AsTask();
if (reading.IsValid)
{
var temperature = Convert.ToSingle(reading.Temperature);
var humidity = Convert.ToSingle(reading.Humidity);
lblTemperature.Text = string.Format("{0:0.0} °C", temperature);
lblHumidity.Text = string.Format("{0:0.0} %", humidity);
_SuccessCount++;
//溫度大於 23 就亮燈(Low),否則就熄燈(High)
_pinLED.Write(temperature > 23 ? GpioPinValue.Low : GpioPinValue.High);
// 將讀取到的溫、濕度資訊送到 Azure IoT Suite
await SendTelemetryData(temperature, humidity);
}
else
{
lblLog.Text = "reading fail";
_FailCount++;
}
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
_FailCount++;
}
finally
{
timer.Start();
}
lblReadingInfo.Text = $"Success Count:{_SuccessCount}, Fail Count:{_FailCount}";
}
/// <summary>
/// 將設備的詳細資料送給Cloud
/// </summary>
/// <returns></returns>
async Task StartDevices()
{
try {
_deviceConnstring = string.Format("HostName={0};DeviceId={1};SharedAccessKey={2}",
_hostName, _deviceId, _deviceKey);
_deviceClient = DeviceClient.CreateFromConnectionString(
_deviceConnstring, TransportType.Http1);
JObject device = new JObject();
JObject deviceProps = new JObject();
deviceProps.Add("DeviceID", _deviceId);
deviceProps.Add("HubEnabledState", 1);
deviceProps.Add("DeviceState", "normal");
deviceProps.Add("UpdatedTime", DateTime.UtcNow);
deviceProps.Add("Manufacturer", "655資訊");
deviceProps.Add("ModelNumber", "Raspberry Pi 2 B+");
deviceProps.Add("SerialNumber", "0521");
deviceProps.Add("FirmwareVersion", "10.0586");
deviceProps.Add("Platform", "Windows10 IoT Core");
deviceProps.Add("Processor", "ARM");
deviceProps.Add("Latitude", 25);
deviceProps.Add("Longitude", 121);
device.Add("DeviceProperties", deviceProps);
device.Add("Commands", new JArray());
device.Add("IsSimulatedDevice", 0);
device.Add("ObjectType", "DeviceInfo");
device.Add("Version", "1.0");
var messageString = JsonConvert.SerializeObject(device);
var message = new Message(Encoding.UTF8.GetBytes(messageString));
await _deviceClient.SendEventAsync(message);
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
}
}
/// <summary>
/// 將讀取到的溫、濕度資訊送到 Azure IoT Suite
/// </summary>
/// <param name="temperature"></param>
/// <param name="humidity"></param>
async Task SendTelemetryData(float temperature, float humidity)
{
try
{
JObject deviceData = new JObject();
deviceData.Add("DeviceId", _deviceId);
deviceData.Add("Temperature", temperature);
deviceData.Add("Humidity", humidity);
var msgString = JsonConvert.SerializeObject(deviceData);
var msg = new Message(Encoding.UTF8.GetBytes(msgString));
await _deviceClient.SendEventAsync(msg);
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
}
}
private async void btnSendDeviceInfo_Click(object sender, RoutedEventArgs e)
{
try
{
await StartDevices();
}
catch (Exception ex)
{
lblLog.Text = ex.ToString();
}
}
}
在 StartDevices 與 SendTelemetryData 的 DeviceId 屬性不同,在寫時要注意一下哦!
參考資料
快速建置物聯網系統: Azure IoT Suite - Remote Monitoring 簡介及客製化
Azure/azure-iot-remote-monitoring
Using PowerShell to connect and configure a device running Windows 10 IoT Core
Raspberry Pi 2 /Windows IOT Core 讀取 DHT22 的溫、濕度資訊
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^