Azure IoT Edge 离线功能示例

Azure IoT Edge Offline capabilities Example

我对如何使用 IoT Edge 离线模式有点困惑。我以为它是开箱即用的!

我的物联网中心位于美国西部。当我断开我的 Edge 设备与网络的连接时,什么也没有发生。重新联网后数据不保存也不重新发送

我只有一个模块将数据发送到 IoT 中心,我可以看到数据通过 Device Explorer Twin 应用程序流动,并将数据保存在数据库中。

断开连接后,等待 5 分钟并重新连接,我在数据库中看不到我在离线模式下尝试发送的数据。 离线时所有消息都丢失了(我正在用日期时间戳对消息进行排序)。

我是不是漏配置了?

知道为什么离线模式对我不起作用吗? 我正在使用 Iot Edge Runtime v1.0.6 和 Windows 容器。

这里是我的测试模块的源代码:

using Microsoft.Azure.Devices.Client;
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Runtime.Loader;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {

        static int monitoringInterval { get; set; } = 60;// 60 seconds
        static System.Timers.Timer testTimer;
        static ModuleClient ioTHubModuleClient;

        static void Main(string[] args)
        {
            Init().Wait();

            StartTestTimer();

            // Wait until the app unloads or is cancelled
            var cts = new CancellationTokenSource();
            AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel();
            Console.CancelKeyPress += (sender, cpe) => cts.Cancel();
            WhenCancelled(cts.Token).Wait();
        }

        /// <summary>
        /// Handles cleanup operations when app is cancelled or unloads
        /// </summary>
        public static Task WhenCancelled(CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<bool>();
            cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).SetResult(true), tcs);
            return tcs.Task;
        }

        /// <summary>
        /// Initializes the ModuleClient and sets up the callback to receive
        /// messages containing temperature information
        /// </summary>
        static async Task Init()
        {
            AmqpTransportSettings amqpSetting = new AmqpTransportSettings(TransportType.Amqp_Tcp_Only);
            ITransportSettings[] settings = { amqpSetting };

            // Open a connection to the Edge runtime
            ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
            await ioTHubModuleClient.OpenAsync();
            Console.WriteLine("IoT Hub module client initialized.");
        }


        static void StartTestTimer()
        {
            Console.WriteLine("Start Monitoring Timer: " + monitoringInterval + " seconds");

            // Set up a timer that triggers every minute.
            testTimer = new System.Timers.Timer();
            testTimer.Interval = monitoringInterval * 1000; // 60 seconds
            testTimer.Elapsed += new System.Timers.ElapsedEventHandler(SendEvent);
            testTimer.Start();

            SendEvent(null, null);
        }


        async static void SendEvent(object sender, System.Timers.ElapsedEventArgs args)
        {
            DateTime today = DateTime.Now;
            Console.WriteLine("[" + today + "] Send Data has started...");

            try
            {                
                //IoT device connection string
                string connectionString = "HostName=xxxxxx.azure-devices.net;DeviceId=IOT-Device1;SharedAccessKey=ett8xxxxxxxxx";

                // Connect to the IoT hub using the MQTT protocol
                DeviceClient _DeviceClient = DeviceClient.CreateFromConnectionString(connectionString, TransportType.Mqtt);
                _DeviceClient.OperationTimeoutInMilliseconds = 10000;

                Dictionary<string, Object> telemetryDataPoint = new Dictionary<string, Object>();

                string dateTime = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
                telemetryDataPoint.Add("DateTime", dateTime);               

                string messageString = JsonConvert.SerializeObject(telemetryDataPoint);
                Message message = new Message(Encoding.ASCII.GetBytes(messageString));

                // Send the telemetry message
                Console.WriteLine("\n*> Sending message: {0}",  messageString);
                await _DeviceClient.SendEventAsync(message).ConfigureAwait(false);
                Console.WriteLine("Message sent!");

            }
            catch (Exception e)
            {
                Console.WriteLine("Message not sent. Connection error to Iot Hub:" + e.Message);
            }

        }

    }

为什么代码在 Init() 中创建了一个 moduleClient,但随后尝试在 SendEvent() 中使用 deviceClient 将消息直接发送到 IoT 中心?这完全绕过了边缘运行时(特别是 edgeHub),这有助于离线存储和转发。

下面是一个正确方法的例子:https://github.com/Azure/iotedge/blob/ad41fec507bb91a2e57a07cd32e287ada0ca08d8/edge-modules/SimulatedTemperatureSensor/src/Program.cs#L95