2

I'm playing around with experimental features from 1.0.10-rc2.

There is a direct method on edgeAgent UploadModuleLogs.

I can call the method from Azure Portal and it works fine. I'm trying to call the method from my module on the same device like this:

static async Task Init()
{
...

  await ioTHubModuleClient.SetMethodHandlerAsync("UploadModuleLogs", UploadModuleLogs, ioTHubModuleClient);
}

private static async Task<MethodResponse> UploadModuleLogs(MethodRequest methodRequest, object userContext)
{
  ModuleClient ioTHubModuleClient = (ModuleClient)userContext;

  // Upload logs
  Console.WriteLine("Invoking method On edgeAgent");

  var payload = @"{
""schemaVersion"": ""1.0"",
""sasUrl"": ""https://..."",
""items"": [
    {
        ""id"": "".*"", 
        ""filter"": {
            ""tail"": 100
        }
    }
],
""encoding"": ""none"", 
""contentType"": ""text""
} ";

  MethodRequest request = new MethodRequest("UploadModuleLogs", Encoding.UTF8.GetBytes(payload));

  string myModuleId = Environment.GetEnvironmentVariable("IOTEDGE_MODULEID");
  string myDeviceId = Environment.GetEnvironmentVariable("IOTEDGE_DEVICEID");

  Console.WriteLine($"{myDeviceId} {myModuleId} - UploadModuleLogs method request at {DateTime.Now}");
  //Console.WriteLine($"{request.DataAsJson}");

  try
  {
    var response = await ioTHubModuleClient.InvokeMethodAsync(myDeviceId, "$edgeAgent", request).ConfigureAwait(false);
    Console.WriteLine($"Received response with status: {response.Status} with message: {response.ResultAsJson}");

    return response;
  }
  catch (Exception ex)
  {
    Console.WriteLine($"Error invoking method {ex}");
  }

  return null;

Trying to run this:

Error invoking method Microsoft.Azure.Devices.Client.Exceptions.DeviceNotFoundException: Device {"message":"Client myDeviceName/$edgeAgent not found"} not registered at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.ExecuteAsync(HttpMethod httpMethod, Uri requestUri, Func3 modifyRequestMessageAsync, Func2 isSuccessful, Func3 processResponseMessageAsync, IDictionary2 errorMappingOverrides, CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.PostAsync[T1,T2](Uri requestUri, T1 entity, IDictionary2 errorMappingOverrides, IDictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.ModuleClient.InvokeMethodAsync(Uri uri, MethodRequest methodRequest, CancellationToken cancellationToken)

Juri
  • 1,531
  • 2
  • 20
  • 43

2 Answers2

1

for module to module communication you should create messages and route from one to the other https://learn.microsoft.com/en-us/azure/iot-edge/module-composition#declare-routes.

Methods are not supported :-(

Setting up a route allows you to call a method on another module which is connected to the same edgeHub:

FROM /messages/modules/{moduleName}/* INTO BrokeredEndpoint("/modules/SimulatedTemperatureSensor/inputs/control")
René
  • 151
  • 7
  • 1
    A module's methods can in fact be invoked by another module as long as both modules are connected to the edgeHub. See [step 3 of this tutorial](https://learn.microsoft.com/en-us/azure/iot-edge/tutorial-deploy-stream-analytics#view-data) where the Stream Analytics module invokes reset method on the temp sensor module. – Venkat Yalla Sep 09 '20 at 15:43
  • You are right @VenkatYalla. Setting up a route alles you to call a message on another module: FROM /messages/modules/{moduleName}/* INTO BrokeredEndpoint("/modules/SimulatedTemperatureSensor/inputs/control") – René Sep 10 '20 at 06:36
  • Route matched with "{action = \"InvokeModuleMethod\", controller = \"Twins\"}". Executing controller action with signature "System.Threading.Tasks.Task InvokeModuleMethodAsync(System.String, System.String, Microsoft.Azure.Devices.Edge.Hub.Http.MethodRequest)" on controller "Microsoft.Azure.Devices.Edge.Hub.Http.Controllers.TwinsController" ("Microsoft.Azure.Devices.Edge.Hub.Http"). Unable to invoke method as edge-device/$edgeAgent is not connected – Juri Sep 10 '20 at 07:41
1

This is expected behavior, other modules cannot invoke edge agent's direct methods. The edge agent does not connect to edgeHub by design as the agent's direct methods are privileged and need service creds to access.

Venkat Yalla
  • 558
  • 2
  • 9
  • i would like to upload logs to a blob. if i unterstand you right, this can't be done from a module? – Juri Sep 10 '20 at 15:28
  • 1
    That is correct, edgeAgent methods can only be invoked from the service side (Portal, CLI, program with service credentials, etc.) – Venkat Yalla Sep 10 '20 at 22:55
  • I was actually thinking of implementing something similar: a module which retrieves the logs of all other modules and upload those logs to log analytics. Now I'm going for another approach where an Azure Function periodically uses an IoT Hub Job to call the UploadLogs method. Then another function must import the logs to Log Analytics. Not really an ideal solution for multiple reasons, but the only one I can currently think of. Are there any other alternatives ? (I know about logspout but I'm unfortunately bound to use windows containers in my solution) – Frederik Gheysels May 27 '21 at 21:33