Azure物联网中心-如何获取什么';设备双胞胎中所需的与报告的属性中较新的属性是什么?

Azure物联网中心-如何获取什么';设备双胞胎中所需的与报告的属性中较新的属性是什么?,azure,iot,azure-iot-hub,Azure,Iot,Azure Iot Hub,我正在使用.NET Core 3读取Azure IoT中心中的设备双胞胎。我想得到属性X,该属性一如既往地存储在所需和报告的属性中。我想买一个新的。此信息写入元数据中 我的问题是,这是通过IoT Hub查询语言实现的,还是我必须从所需和报告中提取并亲自检查?仅支持SQL语句的子集,因此以下示例(device1和twin属性颜色)显示了缺少CASE语句的解决方法: 查询字符串以获取所需的属性作为上次更新的属性: querystring = $"SELECT devices.propert

我正在使用.NET Core 3读取Azure IoT中心中的设备双胞胎。我想得到属性X,该属性一如既往地存储在所需和报告的属性中。我想买一个新的。此信息写入元数据中

我的问题是,这是通过IoT Hub查询语言实现的,还是我必须从所需和报告中提取并亲自检查?

仅支持SQL语句的子集,因此以下示例(device1和twin属性颜色)显示了缺少CASE语句的解决方法:

  • 查询字符串以获取所需的属性作为上次更新的属性:

    querystring = $"SELECT devices.properties.desired.color FROM devices WHERE deviceId = 'device1' and devices.properties.desired.$metadata.color.$lastUpdated > devices.properties.reported.$metadata.color.$lastUpdated";
    
  • 如果返回值为空,我们必须进行第二次查询以获取报告的属性,例如:

     querystring = $"SELECT devices.properties.reported.color FROM devices WHERE deviceId = 'device1' and devices.properties.reported.$metadata.color.$lastUpdated > devices.properties.desired.$metadata.color.$lastUpdated";
    
  • 如果返回值仍然为空,则表示device twin中缺少所需和/或报告的属性,或者deviceId错误

  • 以下代码段显示了上述用法的示例:

    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}'");
            }
        }
    }
    
    此外,还可以创建扩展类来简化代码,请参见以下示例:

    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);
        }
    }
    
    公共静态类JObjectExtensions
    {
    公共静态T GetLastUpdate(此作业对象属性,字符串属性名称)
    {
    JToken desired=properties.SelectToken(“properties.desired”);
    JToken reported=properties.SelectToken(“properties.reported”);
    字符串pathLastUpdated=$“$metadata.{propertyName}.$lastUpdated”;
    需要返回(日期时间)。选择令牌(PathLastUpdate)>(日期时间)已报告。选择令牌(PathLastUpdate)?
    所需的.SelectToken(propertyName).ToObject():reported.SelectToken(propertyName).ToObject();
    }
    公共静态字符串GetLastUpdate(此作业对象属性,字符串属性名称)
    {
    返回GetLastUpdated(属性,propertyName);
    }
    }
    
    上述扩展的以下用法显示了如何根据最新更新的时间戳获得任何所需的vs报告属性:

    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");
    
    color=prop2.GetLastUpdated(propertyName);
    字符串color2=prop2.GetLastUpdated(“test.color”);
    var测试=prop2.GetLastUpdate(“测试”);
    字符串jsontext=prop2.GetLastUpdated(“test”).ToString(Formatting.None);
    var test2=prop2.GetLastUpdated(“测试”);
    int counter=prop2.GetLastUpdated(“计数器”);
    

    请注意,如果属性丢失,将引发异常。

    谢谢。这很有趣。但是,这些是对物联网中心的1次或2次呼叫。我希望只有一个电话。此外,我选择了很多属性,而不仅仅是一个,并且我想为每一个属性选择更新的报告属性和期望属性。有什么想法吗?我在回答中提到过,Azure IoT Hub查询语言中不支持SQL语句大小写(或IIF函数),它将能够根据select语句中的$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");