Azure IoT 中心 - 如何在设备孪生中获取所需的更新与报告的 属性?
Azure IoT Hub - How to get what's newer of desired vs reported property in device twins?
我正在使用 .NET Core 3 从 Azure IoT 中心的设备孪生中读取数据。我想得到 属性 X 并且 属性 一如既往地存储在 desired 和 reported 属性中。我想买一个新的。此信息写入元数据。
我的问题是,这是否可以仅通过 IoT 中心查询语言实现,还是我必须从所需和报告中获取并自行检查?
Azure IoT Hub Query Language只支持SQL语句的子集,所以下面的例子(device1和twin属性color) 显示了缺少 CASE 语句的解决方法:
查询字符串以获取所需的 属性 作为 lastUpdated:
querystring = $"SELECT devices.properties.desired.color FROM devices WHERE deviceId = 'device1' and devices.properties.desired.$metadata.color.$lastUpdated > devices.properties.reported.$metadata.color.$lastUpdated";
如果return值为空,我们必须进行第二次查询以获得报告的属性,例如:
querystring = $"SELECT devices.properties.reported.color FROM devices WHERE deviceId = 'device1' and devices.properties.reported.$metadata.color.$lastUpdated > devices.properties.desired.$metadata.color.$lastUpdated";
如果 return 值仍然为空,则设备孪生中报告 属性 缺少我们想要的 and/or 或设备 ID 错误。
以下代码片段显示了上述用法的示例:
using Microsoft.Azure.Devices;
using System.Linq;
using System;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static string connectionString = "*****";
static async Task Main(string[] args)
{
RegistryManager registryManager = RegistryManager.CreateFromConnectionString(connectionString);
string deviceId = "device1";
string propertyName = "color";
string querystring = $"SELECT devices.properties.desired.{propertyName} FROM devices WHERE deviceId = '{deviceId}' and devices.properties.desired.$metadata.{propertyName}.$lastUpdated > devices.properties.reported.$metadata.{propertyName}.$lastUpdated";
dynamic prop = null;
for (int ii = 0; ii < 2; ii++)
{
var query = registryManager.CreateQuery(querystring);
{
prop = (await query.GetNextAsJsonAsync())?.FirstOrDefault();
if (prop == null)
querystring = $"SELECT devices.properties.reported.{propertyName} FROM devices WHERE deviceId = '{deviceId}' and devices.properties.reported.$metadata.{propertyName}.$lastUpdated > devices.properties.desired.$metadata.{propertyName}.$lastUpdated";
else
break;
}
}
Console.WriteLine(prop ?? $"Not found property '{propertyName}' or device '{deviceId}'");
}
}
}
更新:
在多个属性的情况下,我们必须通过获取的设备孪生实体中的代码单独检查每个 属性。以下代码片段显示了此检查的示例:
// multiple properties
querystring = $"SELECT devices.properties FROM devices WHERE deviceId='{deviceId}'";
var query2 = registryManager.CreateQuery(querystring);
JObject prop2 = JObject.Parse((await query2.GetNextAsJsonAsync())?.FirstOrDefault());
JToken desired = prop2.SelectToken("properties.desired");
JToken reported = prop2.SelectToken("properties.reported");
string pathLastUpdated = $"$metadata.{propertyName}.$lastUpdated";
var color = (DateTime)desired.SelectToken(pathLastUpdated) > (DateTime)reported.SelectToken(pathLastUpdated) ?
(string)desired[propertyName] : (string)reported[propertyName];
// more properties
Console.WriteLine(color);
另外,你可以创建一个扩展class来简化代码,看下面的例子:
public static class JObjectExtensions
{
public static T GetLastUpdated<T>(this JObject properties, string propertyName)
{
JToken desired = properties.SelectToken("properties.desired");
JToken reported = properties.SelectToken("properties.reported");
string pathLastUpdated = $"$metadata.{propertyName}.$lastUpdated";
return (DateTime)desired.SelectToken(pathLastUpdated) > (DateTime)reported.SelectToken(pathLastUpdated) ?
desired.SelectToken(propertyName).ToObject<T>() : reported.SelectToken(propertyName).ToObject<T>();
}
public static string GetLastUpdated(this JObject properties, string propertyName)
{
return GetLastUpdated<string>(properties, propertyName);
}
}
上述扩展的以下用法显示了如何根据其 lastUpdated 时间戳获得任何所需的与报告的属性:
color = prop2.GetLastUpdated(propertyName);
string color2 = prop2.GetLastUpdated("test.color");
var test = prop2.GetLastUpdated<JObject>("test");
string jsontext = prop2.GetLastUpdated<JObject>("test").ToString(Formatting.None);
var test2 = prop2.GetLastUpdated<Test>("test");
int counter = prop2.GetLastUpdated<int>("counter");
注意,属性缺失时抛出异常
我正在使用 .NET Core 3 从 Azure IoT 中心的设备孪生中读取数据。我想得到 属性 X 并且 属性 一如既往地存储在 desired 和 reported 属性中。我想买一个新的。此信息写入元数据。
我的问题是,这是否可以仅通过 IoT 中心查询语言实现,还是我必须从所需和报告中获取并自行检查?
Azure IoT Hub Query Language只支持SQL语句的子集,所以下面的例子(device1和twin属性color) 显示了缺少 CASE 语句的解决方法:
查询字符串以获取所需的 属性 作为 lastUpdated:
querystring = $"SELECT devices.properties.desired.color FROM devices WHERE deviceId = 'device1' and devices.properties.desired.$metadata.color.$lastUpdated > devices.properties.reported.$metadata.color.$lastUpdated";
如果return值为空,我们必须进行第二次查询以获得报告的属性,例如:
querystring = $"SELECT devices.properties.reported.color FROM devices WHERE deviceId = 'device1' and devices.properties.reported.$metadata.color.$lastUpdated > devices.properties.desired.$metadata.color.$lastUpdated";
如果 return 值仍然为空,则设备孪生中报告 属性 缺少我们想要的 and/or 或设备 ID 错误。
以下代码片段显示了上述用法的示例:
using Microsoft.Azure.Devices;
using System.Linq;
using System;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static string connectionString = "*****";
static async Task Main(string[] args)
{
RegistryManager registryManager = RegistryManager.CreateFromConnectionString(connectionString);
string deviceId = "device1";
string propertyName = "color";
string querystring = $"SELECT devices.properties.desired.{propertyName} FROM devices WHERE deviceId = '{deviceId}' and devices.properties.desired.$metadata.{propertyName}.$lastUpdated > devices.properties.reported.$metadata.{propertyName}.$lastUpdated";
dynamic prop = null;
for (int ii = 0; ii < 2; ii++)
{
var query = registryManager.CreateQuery(querystring);
{
prop = (await query.GetNextAsJsonAsync())?.FirstOrDefault();
if (prop == null)
querystring = $"SELECT devices.properties.reported.{propertyName} FROM devices WHERE deviceId = '{deviceId}' and devices.properties.reported.$metadata.{propertyName}.$lastUpdated > devices.properties.desired.$metadata.{propertyName}.$lastUpdated";
else
break;
}
}
Console.WriteLine(prop ?? $"Not found property '{propertyName}' or device '{deviceId}'");
}
}
}
更新:
在多个属性的情况下,我们必须通过获取的设备孪生实体中的代码单独检查每个 属性。以下代码片段显示了此检查的示例:
// multiple properties
querystring = $"SELECT devices.properties FROM devices WHERE deviceId='{deviceId}'";
var query2 = registryManager.CreateQuery(querystring);
JObject prop2 = JObject.Parse((await query2.GetNextAsJsonAsync())?.FirstOrDefault());
JToken desired = prop2.SelectToken("properties.desired");
JToken reported = prop2.SelectToken("properties.reported");
string pathLastUpdated = $"$metadata.{propertyName}.$lastUpdated";
var color = (DateTime)desired.SelectToken(pathLastUpdated) > (DateTime)reported.SelectToken(pathLastUpdated) ?
(string)desired[propertyName] : (string)reported[propertyName];
// more properties
Console.WriteLine(color);
另外,你可以创建一个扩展class来简化代码,看下面的例子:
public static class JObjectExtensions
{
public static T GetLastUpdated<T>(this JObject properties, string propertyName)
{
JToken desired = properties.SelectToken("properties.desired");
JToken reported = properties.SelectToken("properties.reported");
string pathLastUpdated = $"$metadata.{propertyName}.$lastUpdated";
return (DateTime)desired.SelectToken(pathLastUpdated) > (DateTime)reported.SelectToken(pathLastUpdated) ?
desired.SelectToken(propertyName).ToObject<T>() : reported.SelectToken(propertyName).ToObject<T>();
}
public static string GetLastUpdated(this JObject properties, string propertyName)
{
return GetLastUpdated<string>(properties, propertyName);
}
}
上述扩展的以下用法显示了如何根据其 lastUpdated 时间戳获得任何所需的与报告的属性:
color = prop2.GetLastUpdated(propertyName);
string color2 = prop2.GetLastUpdated("test.color");
var test = prop2.GetLastUpdated<JObject>("test");
string jsontext = prop2.GetLastUpdated<JObject>("test").ToString(Formatting.None);
var test2 = prop2.GetLastUpdated<Test>("test");
int counter = prop2.GetLastUpdated<int>("counter");
注意,属性缺失时抛出异常