【问题标题】:Azure IoT Edge module direct method responses shows as [object Object]Azure IoT Edge 模块直接方法响应显示为 [object Object]
【发布时间】:2018-08-22 09:31:21
【问题描述】:

在特定模块上调用直接方法时,我只是在 azure 门户中收到结果[object Object],但我不知道自己做错了什么。 请注意,当我使用 azure IoT SDK for c#(不运行 azure iot 运行时)执行完全相同的操作时,我正确收到了 JSON 对象,并且它不只是显示为 [object Object]。

请注意,我是在 c# 中开发的,并且 docker 容器(用于 IoT 边缘运行时及其模块)正在将 Linux 作为操作系统运行。
我有以下已注册为直接方法的示例方法。

在 iot edge 运行时 Init() 函数中,我执行以下操作:
await ioTHubModuleClient.SetMethodHandlerAsync("Sample1", Sample1, null);

示例方法如下所示:

private static Task<MethodResponse> Sample1(MethodRequest methodRequest, object userContext)
    {            
        // Get data but don't do anything with it... Works fine!
        var data = Encoding.UTF8.GetString(methodRequest.Data);

        var methodResponse = new MethodResponse(Encoding.UTF8.GetBytes("{\"status\": \"ok\"}"), 200);
        return Task.FromResult(methodResponse);
    }  

我可以通过在 Sample1 方法中设置断点来在调试模式下监控这个模块。我找不到我做错了什么?为什么从这个 Sample1 方法返回的响应只是显示为 [object Object],为什么我没有看到 JSON 对象 {"status": "ok"},就像我在不使用 Azure IoT Edge 运行时时看到的那样?

【问题讨论】:

  • 更清楚地说,当在未运行 IoT Edge 运行时的“常规”天蓝色 IoT 设备中注册完全相同的方法时,我在天蓝色门户中看到 JSON 结果,而不仅仅是[对象对象]。如果方法响应来自 azure IoT Edge 模块或“常规”IoT 设备,应该没有什么不同,对吧?

标签: azure-iot-hub azure-iot-sdk azure-iot-edge


【解决方案1】:

Direct Method 的回调结果是对象 Task。它不会序列化为 Json 字符串以显示在 Azure 门户中。但是你可以使用Service Client Sdk获取回调响应,然后序列化为JSON字符串。

最新的Microsoft Azure IoT Hub SDK for C# 支持模块和 IoT Edge。使用 SDK 可以参考这个sample

更新:

在最新的 Azure IoT Hub SDK(Microsoft.Azure.Devices.Client 1.18) 中,请使用 ModuleClinet 而不是 DeviceClient。可以参考以下模块中的代码。

namespace SampleModuleA
{
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Runtime.Loader;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Client.Transport.Mqtt;
    using Microsoft.Azure.Devices.Client;
    using Newtonsoft.Json;
    class Program
    {
        static int counter;

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

            // 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()
        {
            MqttTransportSettings mqttSetting = new MqttTransportSettings(TransportType.Mqtt_WebSocket_Only);
            ITransportSettings[] settings = { mqttSetting };

            // Open a connection to the Edge runtime
            ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
            await ioTHubModuleClient.OpenAsync();
            Console.WriteLine("[{0:HH:mm:ss ffff}]IoT Hub SampleModuleA client initialized.", DateTime.Now);

            await ioTHubModuleClient.SetMethodHandlerAsync("DirectMethod1", DirectMethod1, ioTHubModuleClient);

            // Register callback to be called when a message is received by the module
            await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", PipeMessage, ioTHubModuleClient);
        }

        static async Task<MethodResponse> DirectMethod1(MethodRequest methodRequest, object moduleClient)
        {
            Console.WriteLine("Call DirectMethod1.");
            MethodResponse resp = null;

            //to do Something

            return resp;
        }

        /// <summary>
        /// This method is called whenever the module is sent a message from the EdgeHub. 
        /// It just pipe the messages without any change.
        /// It prints all the incoming messages.
        /// </summary>
        static async Task<MessageResponse> PipeMessage(Message message, object userContext)
        {
            int counterValue = Interlocked.Increment(ref counter);

            var moduleClient = userContext as ModuleClient;
            if (moduleClient == null)
            {
                throw new InvalidOperationException("UserContext doesn't contain " + "expected values");
            }

            byte[] messageBytes = message.GetBytes();
            string messageString = Encoding.UTF8.GetString(messageBytes);
            Console.WriteLine($"Received message: {counterValue}, Body: [{messageString}]");

            if (!string.IsNullOrEmpty(messageString))
            {
                var pipeMessage = new Message(messageBytes);
                foreach (var prop in message.Properties)
                {
                    pipeMessage.Properties.Add(prop.Key, prop.Value);
                }
                await moduleClient.SendEventAsync("output1", pipeMessage);
                Console.WriteLine("Received message sent");
            }
            return MessageResponse.Completed;
        }
    }
}

【讨论】:

  • 好的,但是如果我在未运行 IoT Edge 运行时的“常规”天蓝色物联网设备中注册完全相同的方法,我会在天蓝色门户中看到 JSON 结果,并且不仅仅是[对象对象]。这就是让我觉得我做错了什么的原因,因为它不应该有所不同,对吧?
  • @NoExit,我认为这个问题可能是由于 Azure 门户。您可以发布反馈here。此论坛旨在获取有关新 IoT 服务的反馈:Azure IoT Hub 和 Azure IoT 套件。该论坛将帮助工程团队收集客户和用户的反馈,帮助我们了解路线图并确定路线图的优先级。
  • 感谢@michael-xu-msft。有没有办法使用 DeviceExplorer 工具对在 IoT Edge 运行时上运行的模块调用直接方法调用?如果是这样,方法名称应该是什么?我尝试使用 moduleName/methodName 没有成功,因为我必须以某种方式选择要在哪个模块中调用给定的方法名称,对吧?
  • @NoExit,DeviceExplorer 工具不支持在模块上调用直接方法。我认为您可以尝试使用我帖子中提到的 CallMethod 示例。
  • 感谢@michael-xu-msft 我得到了 CallMethod 示例。遗憾的是,当前的 IoT Edge 运行时没有将连接字符串公开为环境变量,因此我没有让 ReceiverModule 工作。我猜你现在应该使用 ModuleClient 而不是 DeviceClient
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
相关资源
最近更新 更多