我们之前的文章讨论了连接到的方式, 以及在设备应用中监控连接的状态,也介绍了提供的两个基本概念和。在的应用开发中基本上是以为这两个基本的概念展开的。
我们本节来介绍一下如何从设备向云发送消息。
使用向云发送消息
我们先来看一个简单的实例: 使用来向云发送消息。
开始代码之前,我们先介绍一下在设备上和云沟通的几种方法:
向云发送遥测数据:发送遥测数据非常适合设备上有大量的监控数据需要发送到云端的场景。设备用非常高的频率发送各种数据,例如每秒钟监控到的温度,湿度,视频采集数据等等。
向云发送上报属性()数据,关于什么是上报属性,我们之前在里已经向大家介绍过了,实际上就是设备本身状态的一些数据,这些数据是存储在设备对应的文档中,这部分数据不适合大流量的情况。
向云上传文件:非常适合一些类似视频或者音频采集的场景,适合用于批量的, 较大数据量的遥测数据。
我们今天介绍如何向云发送大量的遥测数据。
首先创建一个基本的控制台应用:
使用打开该项目,需要注意的是添加包是为了方便的从命令行输入参数,这里我们使用类定义了两个输入参数以及, 详细的代码请参考该类的定义。
注意
本章的源代码,请从这里下载参考:https://github.com/hylinux/azure-iot-hub-examples/tree/main/DeviceSendMessageToCloud
如果需要参考这部分代码,请大家从上述的demo代码库中下载回来,我们主要的参考部分是如何生成一个的遥测消息的数据的:
while ( !token.IsCancellationRequested )
{
double currentTemperature = minTemperature + rand.NextDouble() * 5; //模拟生成当前的温度.
double currentHumidity = minHumidity + rand.NextDouble() * 20; //模拟生成当前的湿度
//开始创建一个基于`Json`的消息体
string messageBody = JsonSerializer.Serialize(
new
{
temperature = currentTemperature,
humidity = currentHumidity,
}
);
//在基于Json的消息体中,一定要给消息设置contenttype和encoding
using var message = new Message(
Encoding.ASCII.GetBytes(messageBody))
{
ContentType = "application/json",
ContentEncoding = "utf-8",
};
//在生成了消息体之后,消息还可以设置自定义的`Application Properties`, 即应用属性。
//在消息的应用属性里设置一个温度告警.
message.Properties.Add("temperatureAlert", (currentTemperature> 30 )? "true":"false");
//发送消息
await deviceClient.SendEventAsync(message, token);
Console.WriteLine($" > Sending message: ");
await Task.Delay(1000, token);
}
上述代码主要分成三个部分:
使用类的方法序列化消息体,消息体仅仅是一个普通的对象,并将需要上传的消息数据作为属性带入普通的对象就好了。
使用消息类生成正式的消息对象,利用类对使用序列化的数据字节化,并且需要注意的是,由于我们的消息体是序列化之后的数据,我们还需要给消息设置两个必要的元素:
: 指定消息的为
: 指定消息体的字符编码为编码
在消息类的属性中添加应用属性:, 需要注意的是这里的属性值,可以根据业务需要添加。这也是消息格式中的应用属性,关于这个部分我们之后再详细展开来讲述。
最后我们调用的方法 发送我们的遥测数据,至此发送成功。
消息详细讲解
上述代码向我们快速的展示了如何使用基于的向云发送遥测数据,我们之前也强调了遥测数据主要是用于大量的数据上发。帮助我们封装了太多的细节, 创建了标准的消息定义,我们来看一下消息详细的定义包括哪些要素:
预定义的系统属性
由用户自己可以定义的应用属性
消息体,消息体可以包含任何想要包含的类型。
预定义的系统属性是每一个消息都会自动生成的属性,有些属性是可以由用户填充,有些则不可以。
: 用户可以设置,路由关键字是: ()
: 消息被接收的事件,UTC时间,用户无法设置,由自动设置。路由关键字
: 用户可以设置,默认是名字,路由关键字:。
: 设备id, 用户无法设置,路由关键字:
: 模块id, 用户无法设置,路由关键字:
: 设置的包含中的, 用户无法设置,路由关键字:
: 连接认证的方法,用户无法设置,路由关键字:
: 用户可以设置该消息的创建时间,用户设置,路由关键字:
: 和 属性是一样的属性。
: 该属性由设置,用户无法设置,作用是当设备符合要求时设置的, 路由关键字:
: 用户可以设置该属性值,作用是设备符合要求是组件的名字。路由关键字:
注意
我们这里提到一个概念: IoT Hub Play and Plug DeviceIoT Hub Play and Plug Device`。
以上是系统属性。
至于什么是应用属性,应用属性完全可以由用户根据自己的业务逻辑进行定义,例如在应用属性中加入设备的一些特定信息,例如各种硬件序列号,应用的ID等等。
以上是关于消息的三个组成部分,总结一下消息的主要特征:
提供默认的接收设备上传的遥测数据(), 同时这些消息会被保存在中,最多保持7天。
消息最大不能超过。
不允许用户自己设定消息的分区,默认是由设备的进行分区。
用户可以利用应用属性标识消息中和用户业务相关的部分。
重要提示
默认的终结点是和兼容的,因此我们完全可以使用的来消费存储在中的遥测消息。
使用的收取消息
我们上面详细的讨论了遥测数据主要的格式,并且指明遥测数据的终结点和兼容,因此我们来使用一个小例子来接收消息,并研究一下消息的内容。
下面我们来创建应用:
注意
该实例的详细代码,请参考: https://github.com/hylinux/azure-iot-hub-examples/tree/main/ReceiveIoTMessage
我们主要的代码部分是:
static async Task ReceiveMessageFromDeviceAsync(Parameters parameters, CancellationToken token)
{
string connectionString = parameters!.ConnectionString!;
string consumerGroup = parameters.ConsumerGroup;
await using var consumer = new EventHubConsumerClient(
consumerGroup,
connectionString,
parameters.EventHubName
);
Console.WriteLine("开始监听所有分区的消息......");
try
{
await foreach ( PartitionEvent partitionEvent in consumer.ReadEventsAsync(token) )
{
//分区id
Console.WriteLine($"\nMessage received on partition :");
//消息体
string data = Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray());
Console.WriteLine($"\tMessage body: ");
//应用属性
Console.WriteLine("\tApplication properties (set by device):");
foreach (KeyValuePair prop in partitionEvent.Data.Properties)
{
PrintProperties(prop);
}
//系统属性
Console.WriteLine("\tSystem properties (set by IoT hub):");
foreach (KeyValuePair prop in partitionEvent.Data.SystemProperties)
{
PrintProperties(prop);
}
}
} catch (TaskCanceledException ex)
{
Console.WriteLine(ex.ToString());
}
}
static void PrintProperties(KeyValuePair prop)
{
string? propValue = prop.Value is DateTime time
?time.ToString("o"): prop.Value.ToString();
Console.WriteLine($"\t\t: ");
}
运行上述代码可以观察到:
Message received on partition 1:
Message body: {"temperature":24.783567556805977,"humidity":65.33454570237254}
Application properties (set by device):
temperatureAlert: false
System properties (set by IoT hub):
user-id: System.ReadOnlyMemory[0]
content-type: application/json
content-encoding: utf-8
iothub-connection-device-id: testdevice1
iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}
iothub-connection-auth-generation-id: 638050498231177505
content-type: application/json
content-encoding: utf-8
iothub-connection-device-id: testdevice1
iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null} iothub-connection-auth-generation-id: 638050498231177505
iothub-enqueuedtime: 2023-01-02T12:41:09.5770000Z
iothub-message-source: Telemetry
x-opt-sequence-number: 2272
x-opt-offset: 21474853608
x-opt-enqueued-time: 2023/1/2 12:41:09 +00:00
需要强调的是用户如何从上找到和相兼容的信息:
如上图所示:
为兼容的名字
为兼容的
可以创建新的组
连接字符串。
使用上述的输出结果对照一下我们关于消息的理论描述,加深理解。
领取专属 10元无门槛券
私享最新 技术干货