Azure架构

image.png
ADLS - 海量数据存储 为机器学习准备
拿到数据 - 数据的分析 - 数据的应用 RTOS,英文全称Real Time Operating System,即实时操作系统。TSOS,英文全称Time-sharing Operating System,即分时操作系统
区别
RTOS和TSOS各有各的特点,RTOS一般用于相对低速的MCU,比如运动控制类、按键输入等动作要求实时处理的系统,一般要求ms级,甚至us级响应。
分时:现在流行的PC,服务器都是采用这种运行模式,即把CPU的运行分成若干时间片分别处理不同的运算请求。
实时:一般用于单片机上,比如电梯的上下控制中,对于按键等动作要求进行实时处理。
最后
分通过以上分析,可以明确linux是分时系统,不过可以改成实时的如:UCOS就是linux修改而来的实时系统,至于他们的区别,可以引用百度中的类似回答:
分时系统是一个系统可以同时为两个或两个以上的账户服务!
实时系统是能立即对指令做出反应的操作系统!微软的常见系统不能吧!而且还死机!战斗机中的操作系统就是实时的系统,想想如果别人打仗时战斗机中的电脑反应的是飞行员上一条指令或死机了,谁还敢开这架飞机呢?

image.png

IOT hub

Azure IOT Hub是托管的pass服务, 充当网管, 实现设备和后端程序的双向通信, 安全可靠, 可缩放
IOT Hub就是IOT中心, 支持100W个设备的接入, 每天40W消息, 每月只需要200多元.
image.png
IOT带有JSON的数据文件库, 来存储设备信息, Device Twin
IOThub 内置的消息路由, 默认写入eventhub的服务, 用对应的SDK可以方便的读取到
DPS Device Provisioning Service : 海量设备连入云端, 配置的服务

配合限制

https://docs.microsoft.com/zh-cn/azure/iot-hub/iot-hub-devguide-quotas-throttling

使用流程

准备环境

创建IOT hub实例 —>在Iot hub注册设备信息 —- >调用对应sdk做通信
创建资源组 - 创建iot hub实例- 添加设备

发送消息到IOT hub()

例子来源都来自于官网: https://docs.microsoft.com/en-us/azure/iot-hub/
https://docs.microsoft.com/en-us/azure/iot-develop/quickstart-send-telemetry-iot-hub?toc=%2Fazure%2Fiot-hub%2Ftoc.json&bc=%2Fazure%2Fiot-hub%2Fbreadcrumb%2Ftoc.json&pivots=programming-language-java
E:\code\iot-lesson-code\azure-iot-samples-java-master\iot-hub\Quickstarts\simulated-device

  1. // Copyright (c) Microsoft. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. // This application uses the Azure IoT Hub device SDK for Java
  4. // For samples see: https://github.com/Azure/azure-iot-sdk-java/tree/master/device/iot-device-samples
  5. package com.microsoft.docs.iothub.samples;
  6. import com.microsoft.azure.sdk.iot.device.*;
  7. import com.google.gson.Gson;
  8. import java.io.*;
  9. import java.net.URISyntaxException;
  10. import java.util.Random;
  11. import java.util.concurrent.Executors;
  12. import java.util.concurrent.ExecutorService;
  13. public class SimulatedDevice {
  14. // The device connection string to authenticate the device with your IoT hub.
  15. // Using the Azure CLI:
  16. // az iot hub device-identity show-connection-string --hub-name {YourIoTHubName} --device-id MyJavaDevice --output table
  17. private static String connString = "{Your device connection string here}";
  18. // Using the MQTT protocol to connect to IoT Hub
  19. private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
  20. private static DeviceClient client;
  21. // Specify the telemetry to send to your IoT hub.
  22. private static class TelemetryDataPoint {
  23. public double temperature;
  24. public double humidity;
  25. // Serialize object to JSON format.
  26. public String serialize() {
  27. Gson gson = new Gson();
  28. return gson.toJson(this);
  29. }
  30. }
  31. // Print the acknowledgement received from IoT Hub for the telemetry message sent.
  32. private static class EventCallback implements IotHubEventCallback {
  33. public void execute(IotHubStatusCode status, Object context) {
  34. System.out.println("IoT Hub responded to message with status: " + status.name());
  35. if (context != null) {
  36. synchronized (context) {
  37. context.notify();
  38. }
  39. }
  40. }
  41. }
  42. private static class MessageSender implements Runnable {
  43. public void run() {
  44. try {
  45. // Initialize the simulated telemetry.
  46. double minTemperature = 20;
  47. double minHumidity = 60;
  48. Random rand = new Random();
  49. while (true) {
  50. // Simulate telemetry.
  51. double currentTemperature = minTemperature + rand.nextDouble() * 15;
  52. double currentHumidity = minHumidity + rand.nextDouble() * 20;
  53. TelemetryDataPoint telemetryDataPoint = new TelemetryDataPoint();
  54. telemetryDataPoint.temperature = currentTemperature;
  55. telemetryDataPoint.humidity = currentHumidity;
  56. // Add the telemetry to the message body as JSON.
  57. String msgStr = telemetryDataPoint.serialize();
  58. Message msg = new Message(msgStr);
  59. // Add a custom application property to the message.
  60. // An IoT hub can filter on these properties without access to the message body.
  61. msg.setProperty("temperatureAlert", (currentTemperature > 30) ? "true" : "false");
  62. System.out.println("Sending message: " + msgStr);
  63. Object lockobj = new Object();
  64. // Send the message.
  65. EventCallback callback = new EventCallback();
  66. client.sendEventAsync(msg, callback, lockobj);
  67. synchronized (lockobj) {
  68. lockobj.wait();
  69. }
  70. Thread.sleep(1000);
  71. }
  72. } catch (InterruptedException e) {
  73. System.out.println("Finished.");
  74. }
  75. }
  76. }
  77. public static void main(String[] args) throws IOException, URISyntaxException {
  78. // Connect to the IoT hub.
  79. client = new DeviceClient(connString, protocol);
  80. client.open();
  81. // Create new thread and start sending messages
  82. MessageSender sender = new MessageSender();
  83. ExecutorService executor = Executors.newFixedThreadPool(1);
  84. executor.execute(sender);
  85. // Stop the application.
  86. System.out.println("Press ENTER to exit.");
  87. System.in.read();
  88. executor.shutdownNow();
  89. client.closeNow();
  90. }
  91. }

需要修改连接信息:
private static String connString = “{Your device connection string here}”;
对应的在iot hub 中心:
image.png

查看发送的消息

使用工具连接到iot hub, 发送的消息可以用工具读取出来. azure storage explorer 或者 vscode的插件
https://github.com/Azure/azure-iot-explorer/releases?page=1
只需要填入连接iot中心的连接字符串
image.png
image.png
Tip: 要用外网, 公司内网不行.

使用MQTT连接到IOT hub

(官网 https://www.emqx.com/zh )

image.png
如果设备无法使用设备 SDK,仍可使用端口 8883 上的 MQTT 协议连接到公共设备终结点。 在 CONNECT 数据包中,设备应使用以下值:

  • ClientId 字段使用 deviceId。
  • name 字段 自己取
  • 服务器地址: 是iot hub的主机名
  • 端口8883

“用户名”字段使用 {iothubhostname}/{device_id}/?api-version=2021-04-12,其中 {iothubhostname} 是 IoT 中心的完整 CName。例如,如果 IoT 中心的名称为 contoso.azure-devices.net(也是截图中的主机名),设备的名称为 MyDevice01,则完整“用户名”字段应包含:contoso.azure-devices.net/MyDevice01/?api-version=2021-04-12
强烈建议在该字段中包含 api-version。 否则,可能会导致意外行为。

  • “密码”字段使用 SAS 令牌。 对于 HTTPS 和 AMQP 协议,SAS 令牌的格式是相同的:

SharedAccessSignature sig={signature-string}&se={expiry}&sr={URL-encoded-resourceURI}
image.png
测试时,还可以使用跨平台的适用于 Visual Studio Code 的 Azure IoT Tools 或 CLI 扩展命令 az iot hub generate-sas-token 快速生成一个 SAS 令牌

发送“设备到云”消息

成功建立连接后,设备可以使用 devices/{device_id}/messages/events/ 或 devices/{device_id}/messages/events/{property_bag} 作为主题名称将消息发送到 IoT 中心。 {property_bag} 元素可让设备使用 URL 编码格式发送包含其他属性的消息。 例如:
image.png

接收“云到设备”消息

若要从 IoT 中心接收消息,设备应使用 devices/{device_id}/messages/devicebound/# 作为主题筛选器来进行订阅。 主题筛选器中的多级通配符 # 仅用于允许设备接收主题名称中的其他属性。 IoT 中心不允许使用 # 或 ? 通配符筛选子主题。 由于 IoT 中心不是常规用途的发布-订阅消息传送中转站,因此它仅支持存档的主题名称和主题筛选器。
image.png
参考: https://docs.microsoft.com/zh-cn/azure/iot-hub/iot-hub-mqtt-support#using-the-mqtt-protocol-directly-as-a-device

使用java发送和接收消息

文档说明: https://docs.microsoft.com/zh-cn/azure/iot-hub/quickstart-control-device?pivots=programming-language-java

发送示例

Java示例代码: https://github.com/Azure-Samples/azure-iot-samples-java/tree/master/iot-hub/Quickstarts/simulated-device

接收示例

示例代码: https://github.com/Azure-Samples/azure-iot-samples-java/tree/master/iot-hub/Quickstarts/read-d2c-messages
image.png
这个例子面的参数修改, 来源于hub - 内置终结点 - 共享访问策略(要修改为service) 复制下面信息
image.png

  1. // Copyright (c) Microsoft. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. // This application uses the Microsoft Azure Event Hubs Client for Java
  4. // For samples see: https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/eventhubs/azure-messaging-eventhubs/src/samples
  5. // For documentation see: https://docs.microsoft.com/azure/event-hubs/
  6. package com.microsoft.docs.iothub.samples;
  7. import com.azure.core.amqp.AmqpTransportType;
  8. import com.azure.core.amqp.ProxyAuthenticationType;
  9. import com.azure.core.amqp.ProxyOptions;
  10. import com.azure.messaging.eventhubs.EventHubClientBuilder;
  11. import com.azure.messaging.eventhubs.EventHubConsumerAsyncClient;
  12. import com.azure.messaging.eventhubs.models.EventPosition;
  13. import java.net.InetSocketAddress;
  14. import java.net.Proxy;
  15. /**
  16. * A sample demonstrating how to receive events from Event Hubs sent from an IoT Hub device.
  17. * Endpoint=sb://iothub-ns-paul-iot-h-20103882-d96298eeef.servicebus.windows.net/;
  18. * SharedAccessKeyName=service;SharedAccessKey=MyYb30ISu7OsPHjPi8gE38qz8XBhXjPbVcPscn7JFzI=;
  19. * EntityPath=paul-iot-hub
  20. */
  21. public class ReadDeviceToCloudMessages {
  22. private static final String EH_COMPATIBLE_CONNECTION_STRING_FORMAT = "Endpoint=%s/;EntityPath=%s;"
  23. + "SharedAccessKeyName=%s;SharedAccessKey=%s";
  24. // az iot hub show --query properties.eventHubEndpoints.events.endpoint --name {your IoT Hub name}
  25. private static final String EVENT_HUBS_COMPATIBLE_ENDPOINT = "sb://iothub-ns-paul-iot-h-20103882-d96298eeef.servicebus.windows.net/";
  26. // az iot hub show --query properties.eventHubEndpoints.events.path --name {your IoT Hub name}
  27. private static final String EVENT_HUBS_COMPATIBLE_PATH = "paul-iot-hub";
  28. // az iot hub policy show --name service --query primaryKey --hub-name {your IoT Hub name}
  29. private static final String IOT_HUB_SAS_KEY = "service;SharedAccessKey=MyYb30ISu7OsPHjPi8gE38qz8XBhXjPbVcPscn7JFzI=";
  30. private static final String IOT_HUB_SAS_KEY_NAME = "service";
  31. /**
  32. * The main method to start the sample application that receives events from Event Hubs sent from an IoT Hub device.
  33. *
  34. * @param args ignored args.
  35. * @throws Exception if there's an error running the application.
  36. */
  37. public static void main(String[] args) throws Exception {
  38. // Build the Event Hubs compatible connection string.
  39. String eventHubCompatibleConnectionString = String.format(EH_COMPATIBLE_CONNECTION_STRING_FORMAT,
  40. EVENT_HUBS_COMPATIBLE_ENDPOINT, EVENT_HUBS_COMPATIBLE_PATH, IOT_HUB_SAS_KEY_NAME, IOT_HUB_SAS_KEY);
  41. // Setup the EventHubBuilder by configuring various options as needed.
  42. EventHubClientBuilder eventHubClientBuilder = new EventHubClientBuilder()
  43. .consumerGroup(EventHubClientBuilder.DEFAULT_CONSUMER_GROUP_NAME)
  44. .connectionString(eventHubCompatibleConnectionString);
  45. // uncomment to setup proxy
  46. // setupProxy(eventHubClientBuilder);
  47. // uncomment to use Web Sockets
  48. // eventHubClientBuilder.transportType(AmqpTransportType.AMQP_WEB_SOCKETS);
  49. // Create an async consumer client as configured in the builder.
  50. try (EventHubConsumerAsyncClient eventHubConsumerAsyncClient = eventHubClientBuilder.buildAsyncConsumerClient()) {
  51. receiveFromAllPartitions(eventHubConsumerAsyncClient);
  52. // uncomment to run these samples
  53. // receiveFromSinglePartition(eventHubConsumerAsyncClient);
  54. // receiveFromSinglePartitionInBatches(eventHubConsumerAsyncClient);
  55. // Shut down cleanly.
  56. System.out.println("Press ENTER to exit.");
  57. System.in.read();
  58. System.out.println("Shutting down...");
  59. }
  60. }
  61. /**
  62. * This method receives events from all partitions asynchronously starting from the newly available events in
  63. * each partition.
  64. *
  65. * @param eventHubConsumerAsyncClient The {@link EventHubConsumerAsyncClient}.
  66. */
  67. private static void receiveFromAllPartitions(EventHubConsumerAsyncClient eventHubConsumerAsyncClient) {
  68. eventHubConsumerAsyncClient
  69. .receive(false) // set this to false to read only the newly available events
  70. .subscribe(partitionEvent -> {
  71. System.out.println();
  72. System.out.printf("%nTelemetry received from partition %s:%n%s",
  73. partitionEvent.getPartitionContext().getPartitionId(), partitionEvent.getData().getBodyAsString());
  74. System.out.printf("%nApplication properties (set by device):%n%s", partitionEvent.getData().getProperties());
  75. System.out.printf("%nSystem properties (set by IoT Hub):%n%s",
  76. partitionEvent.getData().getSystemProperties());
  77. }, ex -> {
  78. System.out.println("Error receiving events " + ex);
  79. }, () -> {
  80. System.out.println("Completed receiving events");
  81. });
  82. }
  83. /**
  84. * This method queries all available partitions in the Event Hub and picks a single partition to receive
  85. * events asynchronously starting from the newly available event in that partition.
  86. *
  87. * @param eventHubConsumerAsyncClient The {@link EventHubConsumerAsyncClient}.
  88. */
  89. private static void receiveFromSinglePartition(EventHubConsumerAsyncClient eventHubConsumerAsyncClient) {
  90. eventHubConsumerAsyncClient
  91. .getPartitionIds() // get all available partitions
  92. .take(1) // pick a single partition
  93. .flatMap(partitionId -> {
  94. System.out.println("Receiving events from partition id " + partitionId);
  95. return eventHubConsumerAsyncClient
  96. .receiveFromPartition(partitionId, EventPosition.latest());
  97. }).subscribe(partitionEvent -> {
  98. System.out.println();
  99. System.out.printf("%nTelemetry received from partition %s:%n%s",
  100. partitionEvent.getPartitionContext().getPartitionId(), partitionEvent.getData().getBodyAsString());
  101. System.out.printf("%nApplication properties (set by device):%n%s", partitionEvent.getData().getProperties());
  102. System.out.printf("%nSystem properties (set by IoT Hub):%n%s",
  103. partitionEvent.getData().getSystemProperties());
  104. }, ex -> {
  105. System.out.println("Error receiving events " + ex);
  106. }, () -> {
  107. System.out.println("Completed receiving events");
  108. }
  109. );
  110. }
  111. /**
  112. * This method queries all available partitions in the Event Hub and picks a single partition to receive
  113. * events asynchronously in batches of 100 events, starting from the newly available event in that partition.
  114. *
  115. * @param eventHubConsumerAsyncClient The {@link EventHubConsumerAsyncClient}.
  116. */
  117. private static void receiveFromSinglePartitionInBatches(EventHubConsumerAsyncClient eventHubConsumerAsyncClient) {
  118. int batchSize = 100;
  119. eventHubConsumerAsyncClient
  120. .getPartitionIds()
  121. .take(1)
  122. .flatMap(partitionId -> {
  123. System.out.println("Receiving events from partition id " + partitionId);
  124. return eventHubConsumerAsyncClient
  125. .receiveFromPartition(partitionId, EventPosition.latest());
  126. }).window(batchSize) // batch the events
  127. .subscribe(partitionEvents -> {
  128. partitionEvents.toIterable().forEach(partitionEvent -> {
  129. System.out.println();
  130. System.out.printf("%nTelemetry received from partition %s:%n%s",
  131. partitionEvent.getPartitionContext().getPartitionId(), partitionEvent.getData().getBodyAsString());
  132. System.out.printf("%nApplication properties (set by device):%n%s",
  133. partitionEvent.getData().getProperties());
  134. System.out.printf("%nSystem properties (set by IoT Hub):%n%s",
  135. partitionEvent.getData().getSystemProperties());
  136. });
  137. }, ex -> {
  138. System.out.println("Error receiving events " + ex);
  139. }, () -> {
  140. System.out.println("Completed receiving events");
  141. }
  142. );
  143. }
  144. /**
  145. * This method sets up proxy options and updates the {@link EventHubClientBuilder}.
  146. *
  147. * @param eventHubClientBuilder The {@link EventHubClientBuilder}.
  148. */
  149. private static void setupProxy(EventHubClientBuilder eventHubClientBuilder) {
  150. int proxyPort = 8000; // replace with right proxy port
  151. String proxyHost = "{hostname}";
  152. Proxy proxyAddress = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
  153. String userName = "{username}";
  154. String password = "{password}";
  155. ProxyOptions proxyOptions = new ProxyOptions(ProxyAuthenticationType.BASIC, proxyAddress,
  156. userName, password);
  157. eventHubClientBuilder.proxyOptions(proxyOptions);
  158. // To use proxy, the transport type has to be Web Sockets.
  159. eventHubClientBuilder.transportType(AmqpTransportType.AMQP_WEB_SOCKETS);
  160. }
  161. }

使用severless

image.png
一些典型应用: 每隔15分钟清理数据库,; 上传发票, 自动触发函数调用OCR解析发票写入数据库;
image.png
参考: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-maven-intellij
要用最新版本的idea比较好. 使用用vscode开发Azure functions也可以

Prerequisites