nanoFramework.M2Mqtt 5.1.138
前缀已保留
dotnet add package nanoFramework.M2Mqtt --version 5.1.138
NuGet\Install-Package nanoFramework.M2Mqtt -Version 5.1.138
<PackageReference Include="nanoFramework.M2Mqtt" Version="5.1.138" />
paket add nanoFramework.M2Mqtt --version 5.1.138
#r "nuget: nanoFramework.M2Mqtt, 5.1.138"
// Install nanoFramework.M2Mqtt as a Cake Addin #addin nuget:?package=nanoFramework.M2Mqtt&version=5.1.138 // Install nanoFramework.M2Mqtt as a Cake Tool #tool nuget:?package=nanoFramework.M2Mqtt&version=5.1.138
.NET nanoFramework M2Mqtt
欢迎使用 .NET nanoFramework 的 MQTT 客户端库。当前版本支持 v3.1、v3.1.1 和 v5.0。
这是 M2Mqtt MQTT 客户端库的初始移植版本 M2Mqtt。原始项目有一个官方网站 在这里。
从那时起,MQTT 客户端库经历了许多变化,并已适配到 .NET nanoFramework。
构建状态
组件 | 构建状态 | NuGet 包 |
---|---|---|
nanoFramework.M2Mqtt |
项目描述
M2Mqtt 是一个用于物联网和 M2M 通信的 MQTT 客户端。
MQTT,全称为Message Queue Telemetry Transport,是一种轻量级消息协议,允许资源有限的嵌入式设备在某些受限的网络中对异步通信进行操作。
MQTT协议基于发布/订阅模式,因此一个客户端可以订阅一个或多个主题,并接收其他客户端在这些主题上发布的消息。
此库包含一个MQTT客户端示例,您可以使用它连接到任何MQTT代理。
二进制文件作为NuGet包提供。
有关MQTT协议的所有信息,请访问MQTT官方网站。建议您详细了解MQTT协议的工作原理,以便正确使用它。服务质量机制的机理是理解的重要因素。
用法
无论使用哪个版本,用法都是全局相同的。在v3.1.1和v5.0之间存在一些特定性。v5.0版本带来了更多的控制和额外的属性。为了方便起见,它们在属性注释中都被注释为“仅v5.0”。如果您使用的是v3.1或v3.1.1协议的v5.0属性,它们将直接被忽略。
以下是一个基本示例,创建v3.1.1服务器并连接到它
MqttClient mqtt = new MqttClient("test.mosquitto.org", 8883, true, new X509Certificate(CertMosquitto), null, MqttSslProtocols.TLSv1_2);
var ret = mqtt.Connect("nanoTestDevice", true);
if (ret != MqttReasonCode.Success)
{
Debug.WriteLine($"ERROR connecting: {ret}");
mqtt.Disconnect();
return;
}
对于v5.0,您只需在连接之前指定版本即可
MqttClient mqtt = new MqttClient("test.mosquitto.org", 8883, true, new X509Certificate(CertMosquitto), null, MqttSslProtocols.TLSv1_2);
mqtt.ProtocolVersion = MqttProtocolVersion.Version_5;
var ret = mqtt.Connect("nanoTestDevice", true);
if (ret != MqttReasonCode.Success)
{
Debug.WriteLine($"ERROR connecting: {ret}");
mqtt.Disconnect();
return;
}
注意:在两个示例中,连接到Mosquitto服务器需要特定的证书。您可以在示例中找到它。
v5.0特定的认证流程
MQTT版本5.0支持特定的认证流程。在接收到Connect消息后,可以使用认证机制作为挑战请求。在这种情况下,您需要
- 确保将v5设置为协议
- 将属性
IsAuthenticationFlow
设置为true - 注册到
Authentication
事件 - 根据需要发送另一个认证消息或其他相关操作来管理相应的答案。
注意:该协议使用AuthenticationMethod
和AuthenticationData
作为特定机制的属性。
以下是规范中给出的示例
非规范性示例,展示SCRAM挑战
- 客户端到服务器:CONNECT 认证方法="SCRAM-SHA-1" 认证数据=client-first-data
- 服务器到客户端:AUTH rc=0x18 认证方法="SCRAM-SHA-1" 认证数据=server-first-data
- 客户端到服务器 AUTH rc=0x18 认证方法="SCRAM-SHA-1" 认证数据=client-final-data
- 服务器到客户端 CONNACK rc=0 认证方法="SCRAM-SHA-1" 认证数据=server-final-data
非规范性示例,展示Kerberos挑战
- 客户端到服务器 CONNECT 认证方法="GS2-KRB5"
- 服务器到客户端 AUTH rc=0x18 认证方法="GS2-KRB5"
- 客户端到服务器 AUTH rc=0x18 认证方法="GS2-KRB5" 认证数据=initial context token
- 服务器到客户端 AUTH rc=0x18 认证方法="GS2-KRB5" 认证数据=reply context token
- 客户端到服务器 AUTH rc=0x18 认证方法="GS2-KRB5"
- 服务器到客户端 CONNACK rc=0 认证方法="GS2-KRB5" 认证数据=认证结果
在这些机制中,只有当收到包含成功代码的Connack消息时,IsConnected
属性才会设置一次。由于这些认证机制是特定于用户设置,因此这个特定的MqttClient
提供了使用这些机制的能力。
订阅事件
MqttClient提供事件。您可以订阅它们。例如,您可以通过使用v5.0协议连接到Azure IoT Hub获得连接开启时的额外信息。以下示例显示了要使用启用了MQTT v5.0协议的连接到Azure IoT Hub所需要的内容
// Create the client
MqttClient mqtt = new MqttClient(IoTHub, 8883, true, new X509Certificate(CertAzure), null, MqttSslProtocols.TLSv1_2);
// Setup the version
mqtt.ProtocolVersion = MqttProtocolVersion.Version_5;
// Register to events
mqtt.ConnectionOpened += MqttConnectionOpened;
// You can add additional properties
var at = DateTime.UtcNow;
var atString = (at.ToUnixTimeSeconds() * 1000).ToString();
var expiry = at.AddMinutes(40);
var expiryString = (expiry.ToUnixTimeSeconds() * 1000).ToString();
string toSign = $"{IoTHub}\n{DeviceID}\n\n{atString}\n{expiryString}\n";
var hmac = new HMACSHA256(Convert.FromBase64String(Sas));
var sas = hmac.ComputeHash(Encoding.UTF8.GetBytes(toSign));
mqtt.AuthenticationMethod = "SAS";
mqtt.AuthenticationData = sas;
mqtt.UserProperties.Add(new UserProperty("sas-at", atString));
mqtt.UserProperties.Add(new UserProperty("sas-expiry", expiryString));
mqtt.UserProperties.Add(new UserProperty("api-version", "2020-10-01-preview"));
mqtt.UserProperties.Add(new UserProperty("host", IoTHub));
var ret = mqtt.Connect(DeviceID, null, null, false, MqttQoSLevel.AtLeastOnce, false, null, null, true, 60);
// You will have more code here
private static void MqttConnectionOpened(object sender, ConnectionOpenedEventArgs e)
{
Debug.WriteLine($"Connection open");
Debug.WriteLine($" ClientID: {((MqttClient)sender).ClientId}");
Debug.WriteLine($" Assigned client id: {e.Message.AssignedClientIdentifier}");
if (e.Message.AuthenticationData != null) Debug.WriteLine($" Auth data length: {e.Message.AuthenticationData.Length}");
Debug.WriteLine($" Auth method: {e.Message.AuthenticationMethod}");
Debug.WriteLine($" Dup flag: {e.Message.DupFlag}");
Debug.WriteLine($" Max packet size: {e.Message.MaximumPacketSize}");
Debug.WriteLine($" Max QoS: {e.Message.MaximumQoS}");
Debug.WriteLine($" Msg ID: {e.Message.MessageId}");
Debug.WriteLine($" Qos level: {e.Message.QosLevel}");
Debug.WriteLine($" Reason: {e.Message.Reason}");
Debug.WriteLine($" Receive max: {e.Message.ReceiveMaximum}");
Debug.WriteLine($" Rep info: {e.Message.ResponseInformation}");
Debug.WriteLine($" Retain: {e.Message.Retain}");
Debug.WriteLine($" Retain available: {e.Message.RetainAvailable}");
Debug.WriteLine($" Return code: {e.Message.ReturnCode}");
Debug.WriteLine($" Server keep alive: {e.Message.ServerKeepAlive}");
Debug.WriteLine($" Server ref: {e.Message.ServerReference}");
Debug.WriteLine($" Session exp inter: {e.Message.SessionExpiryInterval}");
Debug.WriteLine($" Session present: {e.Message.SessionPresent}");
Debug.WriteLine($" Shared subs available: {e.Message.SharedSubscriptionAvailable}");
Debug.WriteLine($" Shared identifier available: {e.Message.SubscriptionIdentifiersAvailable}");
Debug.WriteLine($" Topic alias max: {e.Message.TopicAliasMaximum}");
Debug.WriteLine($" Num user props: {e.Message.UserProperties.Count}");
foreach (UserProperty prop in e.Message.UserProperties)
{
Debug.WriteLine($" Key : {prop.Name}");
Debug.WriteLine($" Value: {prop.Value}");
}
Debug.WriteLine($" Wildcard available: {e.Message.WildcardSubscriptionAvailable}");
}
示例
M2Mqtt库提供了一个主类MqttClient
,它代表了与代理连接的MQTT客户端。您可以提供代理的IP地址或主机名以及有关MQTT协议的一些可选参数来连接到代理。
连接到代理后,您可以使用Publish()
方法向主题发布消息,并使用Subscribe()
方法订阅主题并接收其上发布的消息。由于MqttClient
类基于事件,所以当您订阅的主题上有消息发布时,您将收到事件通知。您可以在消息发布完成、订阅或取消订阅主题时接收到事件。
以下是一个客户端订阅主题的示例
string MQTT_BROKER_ADDRESS = "192.168.1.2";
// create client instance
MqttClient client = new MqttClient(IPAddress.Parse(MQTT_BROKER_ADDRESS));
// register to message received
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
// subscribe to the topic "/home/temperature" with QoS 2
client.Subscribe(new string[] { "/home/temperature" }, new MqttQoSLevel[] { MqttMsgBase.ExactlyOnce });
// You can add some code here
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// handle message received
}
以下是一个客户端发布到主题的示例
string MQTT_BROKER_ADDRESS = "192.168.1.2";
// create client instance
MqttClient client = new MqttClient(IPAddress.Parse(MQTT_BROKER_ADDRESS));
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
string strValue = Convert.ToString(value);
// publish a message on "/home/temperature" topic with QoS 2
client.Publish("/home/temperature", Encoding.UTF8.GetBytes(strValue), MqttQoSLevel.ExactlyOnce, false);
// More code goes here
忽略证书检查
在某些情况下,在通过TLS连接时忽略证书检查可能很有用。虽然这种场景**不**推荐,但您可以按以下方式调整:
// You can specify no certificate at all
MqttClient mqtt = new MqttClient(IoTHub, 8883, true, null, null, MqttSslProtocols.TLSv1_2);
// And you have to setup the ValidateServerCertificate to false
mqtt.Settings.ValidateServerCertificate = false;
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
反馈和文档
有关文档、提供反馈、问题以及如何贡献的信息,请参阅主存库。
加入我们的Discord社区这里。
鸣谢
此项目的贡献者名单可在贡献者中找到。该库由Paolo Patierno创建和维护,它是Eclipse项目的一部分。
许可证
nanoFramework类库采用MIT许可证。
行为守则
本项目采用贡献者公约中定义的行为守则,以明确期望我们的社区中的行为。有关更多信息,请参阅.NET Foundation行为守则。
.NET Foundation
本项目由.NET Foundation支持。
产品 | 版本 兼容和额外的计算目标框架版本。 |
---|---|
.NET Framework | net是兼容的。 |
-
- nanoFramework.CoreLibrary (>= 1.15.5)
- nanoFramework.Runtime.Events (>= 1.11.18)
- nanoFramework.Runtime.Native (>= 1.6.12)
- nanoFramework.System.Collections (>= 1.5.31)
- nanoFramework.System.Net (>= 1.11.1)
NuGet包 (5)
显示依赖于nanoFramework.M2Mqtt的Top 5 NuGet包
包 | 下载 |
---|---|
nanoFramework.Azure.Devices.Client 此包包含适用于.NET nanoFramework C#项目的.NET nanoFramework.Azure.Devices.Client程序集。这是一个使用MQTT代理的Azure IoT Hub SDK。 |
|
nanoFramework.Aws.IoTCore.Devices 此包包含适用于nanoFramework C#项目的.NET nanoFramework.Aws.IoTCore.Devices程序集。这是一个用于Aws IoTCore的SDK。 |
|
MakoIoT.Device.Services.Mqtt
MAKO-IoT消息总线MQTT库 |
|
MakoIoT.Device.Services.AzureIotHub
为MAKO-IoT提供的AzureIoTHub总线供应商 |
|
DevBot9.NanoFramework.Homie.Utilities
为nanoFramework实现的Homie |
GitHub仓库 (2)
显示依赖于nanoFramework.M2Mqtt的前两个最受欢迎的GitHub仓库
仓库 | 星星 |
---|---|
dotnet/samples
.NET文档引用的示例代码
|
|
nanoframework/Samples
🍬 nanoFramework团队用于测试、概念验证和其他探索性努力的计算示例
|
版本 | 下载 | 上次更新 |
---|---|---|
5.1.138 | 202 | 7/30/2024 |
5.1.130 | 955 | 5/13/2024 |
5.1.128 | 210 | 5/10/2024 |
5.1.126 | 294 | 4/30/2024 |
5.1.123 | 412 | 4/9/2024 |
5.1.120 | 372 | 4/3/2024 |
5.1.116 | 792 | 1/29/2024 |
5.1.114 | 228 | 1/26/2024 |
5.1.112 | 240 | 1/24/2024 |
5.1.110 | 255 | 1/21/2024 |
5.1.107 | 1,478 | 11/10/2023 |
5.1.103 | 187 | 11/9/2023 |
5.1.101 | 255 | 11/8/2023 |
5.1.99 | 99 | 11/8/2023 |
5.1.96 | 674 | 10/10/2023 |
5.1.94 | 975 | 8/28/2023 |
5.1.92 | 230 | 8/28/2023 |
5.1.90 | 245 | 8/28/2023 |
5.1.79 | 3,060 | 1/14/2023 |
5.1.75 | 877 | 12/28/2022 |
5.1.70 | 653 | 12/27/2022 |
5.1.68 | 363 | 12/22/2022 |
5.1.61 | 957 | 11/24/2022 |
5.1.59 | 694 | 11/22/2022 |
5.1.53 | 1,224 | 11/4/2022 |
5.1.48 | 850 | 10/28/2022 |
5.1.46 | 394 | 10/28/2022 |
5.1.44 | 1,943 | 10/26/2022 |
5.1.42 | 622 | 10/25/2022 |
5.1.40 | 386 | 10/25/2022 |
5.1.34 | 3,155 | 10/14/2022 |
5.1.27 | 961 | 10/10/2022 |
5.1.25 | 1,153 | 10/8/2022 |
5.1.22 | 1,695 | 9/22/2022 |
5.1.20 | 992 | 9/22/2022 |
5.1.18 | 1,575 | 9/15/2022 |
5.1.16 | 979 | 9/15/2022 |
5.1.11 | 2,392 | 8/4/2022 |
5.1.9 | 729 | 8/4/2022 |
5.1.6 | 937 | 8/4/2022 |
5.1.4 | 665 | 8/3/2022 |
5.1.2 | 977 | 8/3/2022 |
5.0.2.28 | 673 | 8/3/2022 |
5.0.2.26 | 2,857 | 6/13/2022 |
5.0.2.24 | 1,294 | 6/8/2022 |
5.0.2.22 | 699 | 6/8/2022 |
5.0.2.17 | 1,085 | 5/26/2022 |
5.0.2.15 | 1,603 | 5/18/2022 |
5.0.2.13 | 1,350 | 5/3/2022 |
5.0.2 | 1,887 | 3/28/2022 |
5.0.2-preview.100 | 130 | 3/28/2022 |
5.0.2-preview.98 | 137 | 3/28/2022 |
5.0.2-preview.96 | 130 | 3/28/2022 |
5.0.2-preview.94 | 144 | 3/28/2022 |
5.0.2-preview.91 | 182 | 3/17/2022 |
5.0.2-preview.89 | 135 | 3/17/2022 |
5.0.2-preview.87 | 167 | 3/15/2022 |
5.0.2-preview.85 | 128 | 3/15/2022 |
5.0.2-preview.83 | 148 | 3/15/2022 |
5.0.2-preview.80 | 440 | 2/17/2022 |
5.0.2-preview.78 | 173 | 2/8/2022 |
5.0.2-preview.76 | 200 | 2/4/2022 |
5.0.2-preview.74 | 145 | 2/4/2022 |
5.0.2-preview.72 | 179 | 1/28/2022 |
5.0.2-preview.70 | 141 | 1/28/2022 |
5.0.2-preview.68 | 157 | 1/28/2022 |
5.0.2-preview.65 | 154 | 1/25/2022 |
5.0.2-preview.63 | 151 | 1/21/2022 |
5.0.2-preview.61 | 145 | 1/21/2022 |
5.0.2-preview.59 | 137 | 1/21/2022 |
5.0.2-preview.57 | 136 | 1/21/2022 |
5.0.2-preview.55 | 169 | 1/14/2022 |
5.0.2-preview.53 | 138 | 1/14/2022 |
5.0.2-preview.49 | 210 | 1/5/2022 |
5.0.2-preview.47 | 144 | 1/5/2022 |
5.0.2-preview.46 | 189 | 1/4/2022 |
5.0.2-preview.45 | 172 | 12/31/2021 |
5.0.2-preview.44 | 144 | 12/31/2021 |
5.0.2-preview.43 | 155 | 12/29/2021 |
5.0.2-preview.41 | 190 | 12/17/2021 |
5.0.2-preview.39 | 312 | 12/4/2021 |
5.0.2-preview.37 | 169 | 12/3/2021 |
5.0.2-preview.35 | 174 | 12/3/2021 |
5.0.2-preview.33 | 162 | 12/2/2021 |
5.0.2-preview.31 | 165 | 12/2/2021 |
5.0.2-preview.29 | 165 | 12/1/2021 |
5.0.2-preview.26 | 355 | 11/14/2021 |
5.0.2-preview.24 | 272 | 11/13/2021 |
5.0.2-preview.20 | 206 | 11/12/2021 |
5.0.2-preview.18 | 187 | 10/23/2021 |
5.0.2-preview.15 | 279 | 10/19/2021 |
5.0.2-preview.12 | 168 | 10/18/2021 |
5.0.2-preview.9 | 907 | 9/17/2021 |
5.0.2-preview.6 | 197 | 9/16/2021 |
5.0.2-preview.1 | 633 | 8/2/2021 |
5.0.1 | 947 | 8/2/2021 |
5.0.1-preview.5 | 237 | 7/27/2021 |
5.0.1-preview.4 | 193 | 7/26/2021 |
5.0.1-preview.3 | 250 | 7/17/2021 |
5.0.0 | 592 | 7/16/2021 |
5.0.0-preview.4 | 141 | 7/16/2021 |
5.0.0-preview.3 | 148 | 7/16/2021 |
5.0.0-preview.2 | 780 | 7/3/2021 |
4.6.1-preview.90 | 222 | 7/3/2021 |
4.6.1-preview.89 | 219 | 6/20/2021 |
4.6.1-preview.88 | 256 | 6/19/2021 |
4.6.1-preview.86 | 260 | 6/19/2021 |
4.6.1-preview.85 | 169 | 6/18/2021 |
4.6.1-preview.84 | 157 | 6/17/2021 |
4.6.1-preview.83 | 196 | 6/8/2021 |
4.6.1-preview.82 | 163 | 6/7/2021 |
4.6.1-preview.80 | 165 | 6/7/2021 |
4.6.1-preview.79 | 194 | 6/7/2021 |
4.6.1-preview.78 | 193 | 6/7/2021 |
4.6.1-preview.77 | 199 | 6/6/2021 |
4.6.1-preview.76 | 223 | 6/1/2021 |
4.6.1-preview.75 | 194 | 5/31/2021 |
4.6.1-preview.74 | 200 | 5/30/2021 |
4.6.1-preview.73 | 172 | 5/26/2021 |
4.6.1-preview.72 | 185 | 5/22/2021 |
4.6.1-preview.71 | 220 | 5/21/2021 |
4.6.1-preview.70 | 170 | 5/19/2021 |
4.6.1-preview.69 | 169 | 5/19/2021 |
4.6.1-preview.68 | 181 | 5/19/2021 |
4.6.1-preview.67 | 162 | 5/15/2021 |
4.6.1-preview.66 | 153 | 5/15/2021 |
4.6.1-preview.65 | 162 | 5/13/2021 |
4.6.1-preview.64 | 168 | 5/13/2021 |
4.6.1-preview.63 | 189 | 5/11/2021 |
4.6.1-preview.62 | 167 | 5/6/2021 |
4.6.1-preview.61 | 154 | 5/6/2021 |
4.6.1-preview.60 | 149 | 5/5/2021 |
4.6.1-preview.59 | 146 | 5/5/2021 |
4.6.1-preview.58 | 148 | 5/5/2021 |
4.6.1-preview.57 | 148 | 5/5/2021 |
4.6.1-preview.56 | 193 | 4/10/2021 |
4.6.1-preview.54 | 164 | 3/31/2021 |
4.6.1-preview.52 | 172 | 3/31/2021 |
4.6.1-preview.51 | 165 | 3/29/2021 |
4.6.1-preview.28 | 516 | 12/7/2020 |
4.6.1-preview.27 | 307 | 10/21/2020 |
4.6.1-preview.25 | 291 | 10/21/2020 |
4.6.1-preview.24 | 281 | 10/21/2020 |
4.6.1-preview.22 | 273 | 10/20/2020 |
4.6.1-preview.21 | 329 | 10/1/2020 |
4.6.1-preview.19 | 322 | 10/1/2020 |
4.6.1-preview.18 | 250 | 9/30/2020 |
4.6.1-preview.17 | 267 | 9/30/2020 |
4.6.1-preview.16 | 291 | 9/27/2020 |
4.6.1-preview.15 | 282 | 9/27/2020 |
4.6.1-preview.13 | 272 | 9/19/2020 |
4.6.1-preview.12 | 274 | 9/19/2020 |
4.6.1-preview.11 | 280 | 9/19/2020 |
4.6.1-preview.10 | 318 | 7/2/2020 |
4.6.0-preview.7 | 280 | 6/17/2020 |
4.4.1-preview.5 | 283 | 6/12/2020 |
4.4.1-preview.2 | 310 | 6/11/2020 |
4.4.1-preview.1 | 290 | 6/5/2020 |
4.4.0-preview.30 | 459 | 6/3/2020 |
4.4.0-preview.29 | 286 | 6/3/2020 |
4.4.0-preview.28 | 306 | 6/1/2020 |
4.4.0-preview.27 | 380 | 5/31/2020 |
4.4.0-preview.26 | 284 | 5/29/2020 |
4.4.0-preview.25 | 292 | 5/8/2020 |
4.4.0-preview.24 | 284 | 5/8/2020 |
4.4.0-preview.23 | 280 | 4/27/2020 |
4.4.0-preview.22 | 310 | 4/16/2020 |
4.4.0-preview.20 | 293 | 4/16/2020 |
4.4.0-preview.19 | 272 | 4/14/2020 |
4.4.0-preview.18 | 274 | 4/14/2020 |
4.4.0-preview.17 | 260 | 4/14/2020 |
4.4.0-preview.16 | 270 | 3/25/2020 |
4.4.0-preview.10 | 369 | 11/14/2019 |
4.4.0-preview.9 | 290 | 11/12/2019 |
4.4.0-preview.8 | 283 | 11/8/2019 |
4.4.0-preview.7 | 283 | 11/7/2019 |
4.4.0-preview.5 | 299 | 11/5/2019 |
4.4.0-preview.4 | 308 | 10/30/2019 |
4.4.0-preview.3 | 317 | 10/30/2019 |
4.3.1 | 844 | 10/15/2019 |
4.3.1-preview.17 | 297 | 10/15/2019 |
4.3.1-preview.16 | 290 | 9/24/2019 |
4.3.1-preview.15 | 301 | 9/24/2019 |
4.3.1-preview.14 | 306 | 9/11/2019 |
4.3.1-preview.13 | 300 | 9/11/2019 |
4.3.1-preview.10 | 297 | 7/20/2019 |
4.3.1-preview.6 | 399 | 7/15/2019 |
4.3.1-preview.3 | 312 | 7/12/2019 |
4.3.1-preview.1 | 387 | 7/10/2019 |