通過(guò)IoT中心將環(huán)境數(shù)據(jù)從ProjectLab發(fā)送到Azure
資料介紹
描述
(項(xiàng)目更新為RC-3(2023年3月30日發(fā)布)
此項(xiàng)目向您展示如何使用 IoT 中心連接將環(huán)境數(shù)據(jù)從您的 ProjectLab 發(fā)送到 Azure!
Meadow.Foundation是一個(gè)平臺(tái),用于在 Meadow 上使用 .NET 快速輕松地構(gòu)建連接的事物。它由Wilderness Labs 創(chuàng)建,完全開源并由 Wilderness Labs 社區(qū)維護(hù)。
在您開始這個(gè)項(xiàng)目之前,請(qǐng)確保您的 Meadow 板和開發(fā)環(huán)境是完全最新的。檢查發(fā)行說(shuō)明部分以仔細(xì)檢查。
第 1 步 - 創(chuàng)建 Meadow 應(yīng)用程序項(xiàng)目
在 Visual Studio 2022 for Windows或macOS中創(chuàng)建一個(gè)新的Meadow Application項(xiàng)目并將其命名為MeadowAzureIoTHub 。
第 2 步 - 添加所需的 NuGet 包
對(duì)于這個(gè)項(xiàng)目,搜索并安裝以下 NuGet 包:
第 3 步 - 為 MeadowAzureIoTHub 編寫代碼
該項(xiàng)目具有以下結(jié)構(gòu):
配置文件
讓我們介紹 Meadow 開機(jī)時(shí)自動(dòng)使用的所有三個(gè)配置文件。
app.config.yaml
# Uncomment additional options as needed.
# To learn more about these config options, including custom application configuration settings, check out the Application Settings Configuration documentation.
# http://developer.wildernesslabs.co/Meadow/Meadow.OS/Configuration/Application_Settings_Configuration/
Lifecycle:
# Control whether Meadow will restart when an unhandled app exception occurs. Combine with Lifecycle > AppFailureRestartDelaySeconds to control restart timing.
RestartOnAppFailure: false
# When app set to restart automatically on app failure,
# AppFailureRestartDelaySeconds: 15
# Adjust the level of logging detail.
Logging:
LogLevel:
Default: "Information"
meadow.config.yaml
meadow.config.yaml 文件可用于設(shè)置通用板和系統(tǒng)配置設(shè)置。這包括操作系統(tǒng)和設(shè)備級(jí)別的設(shè)置,例如設(shè)備名稱、默認(rèn)網(wǎng)絡(luò)行為和網(wǎng)絡(luò)設(shè)置。
# Uncommented these options as needed.
# To learn more about these config options, check out the OS & Device Configuration documentation.
# http://developer.wildernesslabs.co/Meadow/Meadow.OS/Configuration/OS_Device_Configuration/
Device:
# Name of the device on the network.
Name: MeadowAzureIoTHub
# Uncomment if SD card hardware present on this hardware (e.g., Core-Compute module with SD add-on)? Optional; default value is `false`.
SdStorageSupported: true
# Control how the ESP coprocessor will start and operate.
Coprocessor:
# Should the ESP32 automatically attempt to connect to an access point at startup?
# If set to true, wifi.config.yaml credentials must be stored in the device.
AutomaticallyStartNetwork: true
# Should the ESP32 automatically reconnect to the configured access point?
AutomaticallyReconnect: true
# Maximum number of retry attempts for connections etc. before an error code is returned.
MaximumRetryCount: 7
# Network configuration.
Network:
# Which interface should be used?
DefaultInterface: WiFi
# Automatically attempt to get the time at startup?
GetNetworkTimeAtStartup: true
# Time synchronization period in seconds.
NtpRefreshPeriodSeconds: 600
# Name of the NTP servers.
NtpServers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
- 3.pool.ntp.org
# IP addresses of the DNS servers.
DnsServers:
- 1.1.1.1
- 8.8.8.8
wifi.config.yaml
wifi.config.yaml 文件可用于設(shè)置默認(rèn) Wi-Fi 接入點(diǎn)和該接入點(diǎn)的密碼。
# To enable automatically connecting to a default network, make sure to enable the Coprocessor > AutomaticallyStartNetwork value in meadow.config.yaml.
Credentials:
Ssid: SSID
Password: PASSWORD
注意:確保在每個(gè)文件的“屬性”窗口中將“復(fù)制到輸出目錄”設(shè)置為“始終” 。
圖片資產(chǎn)
在此項(xiàng)目中,我們將使用一些圖像和圖標(biāo)來(lái)指示我們Meadow何時(shí)加入我們的 WiFi 網(wǎng)絡(luò)以及何時(shí)通過(guò) IoT Hub 將數(shù)據(jù)發(fā)送到 Azure 。您可以從附件部分下載它們。
注意:確保這些圖像中的每一個(gè)都在“屬性”面板中將“構(gòu)建操作”設(shè)置為“嵌入式資源” 。
源代碼
現(xiàn)在我們將介紹此項(xiàng)目中使用的所有 C# 類。
Secrets.cs
public class Secrets { ///
/// Name of the Azure IoT Hub created /// summary> public const string HUB_NAME = "HUB_NAME"; ///
/// Name of the Azure IoT Hub created /// summary> public const string DEVICE_ID = "DEVICE_ID"; ///
/// example "SharedAccessSignature sr=MeadowIoTHub ..... " /// summary> public const string SAS_TOKEN = "SharedAccessSignature..."; }
在此類中,您需要根據(jù) Azure IoT 中心配置設(shè)置適當(dāng)?shù)闹怠?/font>您可以按照這篇博文一步一步地操作,其中會(huì)向您展示如何做到這一點(diǎn)。
IotHubManager.cs
public class IotHubManager
{
private const string HubName = Secrets.HUB_NAME;
private const string SasToken = Secrets.SAS_TOKEN;
private const string DeviceId = Secrets.DEVICE_ID;
private Connection connection;
private SenderLink sender;
public IotHubManager() { }
public async Task Initialize()
{
string hostName = HubName + ".azure-devices.net";
string userName = DeviceId + "@sas." + HubName;
string senderAddress = "devices/" + DeviceId + "/messages/events";
Resolver.Log.Info("Create connection factory...");
var factory = new ConnectionFactory();
Resolver.Log.Info("Create connection ...");
connection = await factory.CreateAsync(new Address(hostName, 5671, userName, SasToken));
Resolver.Log.Info("Create session ...");
var session = new Session(connection);
Resolver.Log.Info("Create SenderLink ...");
sender = new SenderLink(session, "send-link", senderAddress);
}
public Task SendEnvironmentalReading((Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance) reading)
{
try
{
Resolver.Log.Info("Create payload");
string messagePayload = $"{{"Temperature":{reading.Temperature.Value.Celsius}," +
$""Humidity":{reading.Humidity.Value.Percent}," +
$""Pressure":{reading.Pressure.Value.Millibar}}}";
Resolver.Log.Info("Create message");
var message = new Message(Encoding.UTF8.GetBytes(messagePayload));
message.ApplicationProperties = new Amqp.Framing.ApplicationProperties();
Resolver.Log.Info("Send message");
sender.Send(message, null, null);
Resolver.Log.Info($"*** DATA SENT - Temperature - {reading.Temperature.Value.Celsius}, Humidity - {reading.Humidity.Value.Percent}, Pressure - {reading.Pressure.Value.Millibar} ***");
}
catch (Exception ex)
{
Resolver.Log.Info($"-- D2C Error - {ex.Message} --");
}
return Task.CompletedTask;
}
}
此類用于與 Azure IoT 中心建立連接并通過(guò) HTU21D 傳感器發(fā)送環(huán)境讀數(shù)。
DisplayController.cs
public class DisplayController
{
private static readonly Lazy instance =
new Lazy(() => new DisplayController());
public static DisplayController Instance => instance.Value;
static Color backgroundColor = Color.FromHex("#23ABE3");
static Color foregroundColor = Color.Black;
CancellationTokenSource token;
protected BufferRgb888 imgConnecting, imgConnected, imgRefreshing, imgRefreshed;
protected MicroGraphics graphics;
private DisplayController() { }
public void Initialize(IGraphicsDisplay display)
{
imgConnected = LoadJpeg("img_wifi_connected.jpg");
imgConnecting = LoadJpeg("img_wifi_connecting.jpg");
imgRefreshing = LoadJpeg("img_refreshing.jpg");
imgRefreshed = LoadJpeg("img_refreshed.jpg");
graphics = new MicroGraphics(display)
{
CurrentFont = new Font12x16(),
Stroke = 3,
};
graphics.Clear(true);
}
BufferRgb888 LoadJpeg(string fileName)
{
var jpgData = LoadResource(fileName);
var decoder = new JpegDecoder();
decoder.DecodeJpeg(jpgData);
return new BufferRgb888(decoder.Width, decoder.Height, decoder.GetImageData());
}
protected void DrawBackground()
{
var logo = LoadJpeg("img_meadow.jpg");
graphics.Clear(backgroundColor);
graphics.DrawBuffer(
x: graphics.Width / 2 - logo.Width / 2,
y: 63,
buffer: logo);
graphics.DrawText(graphics.Width / 2, 160, "Azure IoT Hub", Color.Black, alignmentH: HorizontalAlignment.Center);
}
protected byte[] LoadResource(string filename)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = $"MeadowAzureIoTHub.{filename}";
using Stream stream = assembly.GetManifestResourceStream(resourceName);
using var ms = new MemoryStream();
stream.CopyTo(ms);
return ms.ToArray();
}
public void ShowSplashScreen()
{
DrawBackground();
graphics.Show();
}
public async Task ShowConnectingAnimation()
{
token = new CancellationTokenSource();
bool alternateImg = false;
while (!token.IsCancellationRequested)
{
alternateImg = !alternateImg;
graphics.DrawBuffer(204, 6, alternateImg ? imgConnecting : imgConnected);
graphics.Show();
await Task.Delay(500);
}
}
public void ShowConnected()
{
token.Cancel();
graphics.DrawBuffer(204, 6, imgConnected);
graphics.DrawBuffer(6, 6, imgRefreshed);
graphics.DrawRectangle(0, 32, 240, 208, backgroundColor, true);
graphics.DrawCircle(120, 75, 50, foregroundColor);
graphics.DrawText(120, 59, "Temp", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.DrawCircle(62, 177, 50, foregroundColor);
graphics.DrawText(62, 161, "Pres", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.DrawCircle(178, 177, 50, foregroundColor);
graphics.DrawText(178, 161, "Hum", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.Show();
}
public async Task StartSyncCompletedAnimation((Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance) reading)
{
graphics.DrawBuffer(6, 6, imgRefreshing);
graphics.Show();
await Task.Delay(TimeSpan.FromSeconds(1));
graphics.DrawRectangle(75, 78, 90, 16, backgroundColor, true);
graphics.DrawText(120, 78, $"{reading.Temperature.Value.Celsius:N1}°C", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.DrawRectangle(17, 180, 90, 16, backgroundColor, true);
graphics.DrawText(62, 180, $"{reading.Pressure.Value.StandardAtmosphere:N1}atm", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.DrawRectangle(133, 180, 90, 16, backgroundColor, true);
graphics.DrawText(178, 180, $"{reading.Humidity.Value.Percent:N2}%", foregroundColor, alignmentH: HorizontalAlignment.Center);
graphics.DrawBuffer(6, 6, imgRefreshed);
graphics.Show();
}
}
此類使用MicroGraphics在 ST7789 顯示屏中繪制所有 UI,例如在應(yīng)用程序啟動(dòng)時(shí)顯示啟動(dòng)畫面、更新溫度/濕度值,以及 WiFi 和同步指示器以了解消息何時(shí)發(fā)送到 IoT 中心。
MeadowApp.cs
public class MeadowApp : App
{
RgbPwmLed onboardLed;
IProjectLabHardware projectLab;
IotHubManager amqpController;
public override Task Initialize()
{
onboardLed = new RgbPwmLed(
Device.Pins.OnboardLedRed,
Device.Pins.OnboardLedGreen,
Device.Pins.OnboardLedBlue);
onboardLed.SetColor(Color.Red);
try
{
amqpController = new IotHubManager();
var wifi = Device.NetworkAdapters.Primary();
wifi.NetworkConnected += NetworkConnected;
projectLab = ProjectLab.Create();
projectLab.EnvironmentalSensor.Updated += EnvironmentalSensorUpdated;
DisplayController.Instance.Initialize(projectLab.Display);
DisplayController.Instance.ShowSplashScreen();
DisplayController.Instance.ShowConnectingAnimation();
}
catch (Exception ex)
{
Resolver.Log.Error($"Failed to Connect: {ex.Message}");
}
return Task.CompletedTask;
}
private async void NetworkConnected(INetworkAdapter sender, NetworkConnectionEventArgs args)
{
DisplayController.Instance.ShowConnected();
await amqpController.Initialize();
projectLab.EnvironmentalSensor.StartUpdating(TimeSpan.FromSeconds(15));
onboardLed.SetColor(Color.Green);
}
private async void EnvironmentalSensorUpdated(object sender, IChangeResult<(Meadow.Units.Temperature? Temperature, Meadow.Units.RelativeHumidity? Humidity, Meadow.Units.Pressure? Pressure, Meadow.Units.Resistance? GasResistance)> e)
{
await amqpController.SendEnvironmentalReading(e.New);
await DisplayController.Instance.StartSyncCompletedAnimation(e.New);
}
}
MeadowApp主類初始化 ProjectLab 上的顯示和環(huán)境傳感器,一旦 Meadow 加入 WiFi 網(wǎng)絡(luò)并與 Azure 建立連接,它將開始每 15 秒讀取一次室溫、濕度和壓力。
第 5 步 - 運(yùn)行項(xiàng)目
單擊Visual Studio中的“運(yùn)行”按鈕。它應(yīng)該類似于以下 GIF:
當(dāng)應(yīng)用程序運(yùn)行時(shí),您應(yīng)該有類似這樣的輸出:
Create connection factory...
Create connection ...
Create session ...
Create SenderLink ...
Create payload
Create message
Send message
*** DATA SENT - Temperature - 27.9073605400976, Humidity - 29.4871487326418, Pressure - 1020.90879412913 ***
Create payload
Create message
Send message
*** DATA SENT - Temperature - 28.0586979364511, Humidity - 29.1871445300884, Pressure - 1020.8916192437 ***
Create payload
Create message
Send message
*** DATA SENT - Temperature - 28.179768034583, Humidity - 28.9781536413303, Pressure - 1020.90573418024 ***
...
這可確保您已建立與Azure的連接,并且該應(yīng)用每 15 秒向IoT 中心發(fā)送一次數(shù)據(jù)。
您還可以轉(zhuǎn)到Azure門戶,打開IoT 中心概述部分,然后查看傳入消息的數(shù)量隨著時(shí)間的推移而增加。
?
查看 Meadow.Foundation!
就您可以使用 Meadow.Foundation 做的大量令人興奮的事情而言,這個(gè)項(xiàng)目只是冰山一角。
它帶有一個(gè)龐大的外設(shè)驅(qū)動(dòng)程序庫(kù),其中包含適用于最常見(jiàn)傳感器和外設(shè)的驅(qū)動(dòng)程序。
- 它帶有一個(gè)龐大的外設(shè)驅(qū)動(dòng)程序庫(kù),其中包含適用于最常見(jiàn)傳感器和外設(shè)的驅(qū)動(dòng)程序。
- 外設(shè)驅(qū)動(dòng)程序封裝了核心邏輯并公開了一個(gè)簡(jiǎn)單、干凈、現(xiàn)代的 API。
- 該項(xiàng)目得到了不斷發(fā)展的社區(qū)的支持,該社區(qū)不斷致力于構(gòu)建酷炫的互聯(lián)事物,并且總是樂(lè)于幫助新來(lái)者和討論新項(xiàng)目。
參考
- 從NodeMCU捕獲數(shù)據(jù)并將其發(fā)送到Thingsio.ai云
- 如何將數(shù)據(jù)從M5Stack StickC發(fā)送到Delphi
- 通過(guò)藍(lán)牙將傳感器數(shù)據(jù)發(fā)送到AWS云
- 通過(guò)藍(lán)牙將消息發(fā)送到連接到STM32板的LCD顯示器
- 如何將字節(jié)發(fā)送到8x8 LED矩陣
- 將數(shù)據(jù)發(fā)送到云端開源硬件
- 使用ESP 01將DHT11測(cè)量的溫度和濕度數(shù)據(jù)發(fā)送到服務(wù)器
- Arduino通過(guò)串行將溫度發(fā)送到網(wǎng)絡(luò)
- 如何將手機(jī)連接到Azure IoT Central
- Arduino將傳感器數(shù)據(jù)發(fā)送到MySQL服務(wù)器
- 【程序+PCB】STM32F107VC單片機(jī)利用外部中斷和DMA獲取OV2640攝像頭拍攝的照片,并通過(guò)串口發(fā)送到電腦上(HAL+LL庫(kù)
- 調(diào)整AVR-IoT WG的用途以連接到AWS 10次下載
- 使用AVR單片機(jī)的I2C讀取MPU6050發(fā)送到串口的程序免費(fèi)下載 9次下載
- C8051F020實(shí)現(xiàn)ADC采樣芯片外的模擬電壓通過(guò)LCD顯示并通過(guò)串口發(fā)送到PC機(jī) 14次下載
- 使用STM32的dht11溫濕度檢測(cè)通過(guò)GSM模塊發(fā)送到手機(jī)的代碼免費(fèi)下載 5次下載
- 西門子博途:發(fā)送函數(shù)的編程示例 3621次閱讀
- 遠(yuǎn)程監(jiān)控系統(tǒng)通過(guò)短信發(fā)送電子郵件 1800次閱讀
- GRM模塊傳送數(shù)據(jù)給組態(tài)王的具體上位機(jī)配置方法 1506次閱讀
- UVM sequence機(jī)制中response的簡(jiǎn)單使用 2469次閱讀
- 數(shù)據(jù)是怎么樣保證準(zhǔn)確的從客戶端發(fā)送到服務(wù)器端 2123次閱讀
- 怎么實(shí)現(xiàn)基于MFRC522的區(qū)塊鏈RFID掃描儀設(shè)計(jì) 2377次閱讀
- 如何設(shè)置Arduino IoT將消息發(fā)送到云板顯示器 2303次閱讀
- 如何使用SIM900A將傳感器數(shù)據(jù)發(fā)送到網(wǎng)站 3406次閱讀
- 為什么傳統(tǒng)的FPGA無(wú)法將智能傳送到邊緣 3412次閱讀
- 淺談分裂LVDS信號(hào)設(shè)計(jì)技術(shù) 2622次閱讀
- STEP7報(bào)告系統(tǒng)錯(cuò)誤的解決辦法 9044次閱讀
- 以太網(wǎng)通信:S7-1200與S7-300/400之間的數(shù)據(jù)交換 9312次閱讀
- 如何CAN總線數(shù)據(jù)通過(guò)無(wú)線的方式發(fā)送到終端上 7021次閱讀
- 數(shù)據(jù)存儲(chǔ)在遠(yuǎn)程數(shù)據(jù)中心的遠(yuǎn)程服務(wù)器上時(shí),究竟會(huì)發(fā)生什么? 3207次閱讀
- 遠(yuǎn)程監(jiān)控數(shù)據(jù)的計(jì)算機(jī)通信終端設(shè)計(jì)與實(shí)現(xiàn) 2812次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
- 1.06 MB | 532次下載 | 免費(fèi)
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費(fèi)
- 3TC358743XBG評(píng)估板參考手冊(cè)
- 1.36 MB | 330次下載 | 免費(fèi)
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費(fèi)
- 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費(fèi)
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費(fèi)
- 7元宇宙底層硬件系列報(bào)告
- 13.42 MB | 182次下載 | 免費(fèi)
- 8FP5207XR-G1中文應(yīng)用手冊(cè)
- 1.09 MB | 178次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費(fèi)
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費(fèi)
- 4開關(guān)電源設(shè)計(jì)實(shí)例指南
- 未知 | 21549次下載 | 免費(fèi)
- 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費(fèi)
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費(fèi)
- 7電子制作實(shí)例集錦 下載
- 未知 | 8113次下載 | 免費(fèi)
- 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
- 0.00 MB | 6656次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191187次下載 | 免費(fèi)
- 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
- 158M | 183279次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138040次下載 | 免費(fèi)
評(píng)論
查看更多