Azure IoT Edge 模块直接方法响应显示为 [object Object]
Azure IoT Edge module direct method responses shows as [object Object]
在特定模块上调用直接方法时,我只是在 Azure 门户中收到结果 [object Object]
,但我不知道自己做错了什么。
请注意,当我使用适用于 c# 的 azure IoT SDK(没有 运行 azure 物联网运行时)执行完全相同的操作时,我正确地收到了 JSON 对象,它不仅显示为 [object Object]。
请注意,我正在用 c# 开发它,docker 容器(用于物联网边缘运行时及其模块)是 运行 Linux as OS。
我有以下示例方法,我已将其注册为直接方法。
在物联网边缘运行时 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-object {"status": "ok"}
,就像我在不使用 Azure IoT Edge 运行时时所做的那样?
直接方法的回调结果是对象 Task< MethodResponse >。它不会序列化为 Json 字符串以显示在 Azure 门户中。但是你可以使用Service Client Sdk获取回调响应,然后序列化为JSON字符串。
最新Microsoft Azure IoT Hub SDK for C# supports Modules and IoT Edge. You can refer to this sample使用SDK。
更新:
在最新的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;
}
}
}
在特定模块上调用直接方法时,我只是在 Azure 门户中收到结果 [object Object]
,但我不知道自己做错了什么。
请注意,当我使用适用于 c# 的 azure IoT SDK(没有 运行 azure 物联网运行时)执行完全相同的操作时,我正确地收到了 JSON 对象,它不仅显示为 [object Object]。
请注意,我正在用 c# 开发它,docker 容器(用于物联网边缘运行时及其模块)是 运行 Linux as OS。
我有以下示例方法,我已将其注册为直接方法。
在物联网边缘运行时 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-object {"status": "ok"}
,就像我在不使用 Azure IoT Edge 运行时时所做的那样?
直接方法的回调结果是对象 Task< MethodResponse >。它不会序列化为 Json 字符串以显示在 Azure 门户中。但是你可以使用Service Client Sdk获取回调响应,然后序列化为JSON字符串。
最新Microsoft Azure IoT Hub SDK for C# supports Modules and IoT Edge. You can refer to this sample使用SDK。
更新:
在最新的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;
}
}
}