0
votes

I'm implementing a Azure Function to send a message to device on Iot Hub event trigger. The problem I'm getting a lot of compile errors with undefined namespaces.

The example is based on this article: https://sandervandevelde.wordpress.com/2016/06/14/closing-the-windows-iot-core-feedback-loop-using-azure-functions/

using System;
using Microsoft.Azure.Devices;
using System.Text;
using Newtonsoft.Json;

public static void Run(string myIoTHubMessage, ILogger log)
{
    var connectionString = "HostName=iot-hub-teste.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=hiden";

    var serviceClient = ServiceClient.CreateFromConnectionString(connectionString);

    var message = JsonConvert.DeserializeObject<Command>(myEventHubMessage);

    var commandMessage = new Message(Encoding.ASCII.GetBytes("Cloud to device message."));

    serviceClient.SendAsync("MyNodeDevice", commandMessage);
}

project.json

{
  "frameworks": {
  "net46":{
    "dependencies": {
      "Microsoft.Azure.Devices": "1.4.1"
      }
    }
  }
}

The errors:

2019-08-23T18:03:47.255 [Error] Function compilation error
Microsoft.CodeAnalysis.Scripting.CompilationErrorException : Script compilation failed.
   at async Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.CreateFunctionTarget(CancellationToken cancellationToken) at C:\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\DotNetFunctionInvoker.cs : 314
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.Azure.WebJobs.Script.Description.FunctionLoader`1.GetFunctionTargetAsync[T](Int32 attemptCount) at C:\azure-webjobs-sdk-script\src\WebJobs.Script\Description\FunctionLoader.cs : 55
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.GetFunctionTargetAsync(Boolean isInvocation) at C:\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\DotNetFunctionInvoker.cs : 183
2019-08-23T18:03:47.427 [Error] run.csx(3,23): error CS0234: The type or namespace name 'Devices' does not exist in the namespace 'Microsoft.Azure' (are you missing an assembly reference?)
2019-08-23T18:03:47.477 [Error] run.csx(13,25): error CS0103: The name 'ServiceClient' does not exist in the current context
2019-08-23T18:03:47.541 [Error] run.csx(15,49): error CS0246: The type or namespace name 'Command' could not be found (are you missing a using directive or an assembly reference?)
2019-08-23T18:03:47.630 [Error] run.csx(15,58): error CS0103: The name 'myEventHubMessage' does not exist in the current context
2019-08-23T18:03:47.694 [Error] run.csx(17,30): error CS0246: The type or namespace name 'Message' could not be found (are you missing a using directive or an assembly reference?)
2019-08-23T18:03:47.766 [Error] Executed 'Functions.msg_to_device' (Failed, Id=de327298-1973-4bc5-82b6-0c7b05835dae)
Script compilation failed.
2

2 Answers

0
votes

1) Please add reference to Microsoft.Azure.Devices(1.18.1) and Microsoft.Azure.Devices.Client(1.21.0) in project.json and then include this in Function code

           using Microsoft.Azure.Devices;
           using Microsoft.Azure.Devices.Client;

2)The command class which is in the blogpost is missing:

            public class Command
            {
              public string devicename {get; set;}
              public int action {get; set;}
            }

3) There isn't any reference for myEventHubMessage. You are using myIoTHubMessage in place of that.

4)using Microsoft.Azure.Devices.Client should get you Message class.

This is how I did from plain C# class .Probably you can tweak this code as per your need in Azure Functions.

         CloudToDeviceMethod cloudtoDeviceMethod = new          
         CloudToDeviceMethod(DeviceMethod, 
         TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)); 

         ServiceClient serviceClient = null;

         serviceClient = 
         ServiceClient.CreateFromConnectionString("HostName=myhub.azure- 
         devices.net;SharedAccessKeyName=service;SharedAccessKey=xxxxxxxxxxxxxxxx");

         await serviceClient.OpenAsync();  

         var response=await serviceClient.InvokeDeviceMethodAsync(DeviceId, 
         cloudtoDeviceMethod);   

         var json = @"{""Response:" + 
         response.GetPayloadAsJson()+@""",Status:""" + 
         response.Status + @"}";    

         if (serviceClient != null)
         {
            await serviceClient.CloseAsync();
         }
0
votes

Testing shows that Microsoft.Azure.Devices has dependency on Newtonsoft.Json. The good part is in the blog that dependency is added.Could you please try adding dependency to Newtonsoft.Json(9.0.1) in project.json and try. By all means it looks like these packages Microsoft.Azure.Devices and Microsoft.Azure.Devices.Client are not being installed and that is why code is complaining that namespace doesn't exists.

Another alternative would be to have functions written in Visual Studio first and then deploy it to Azure.That way you have luxury of testing all dependencies in your machine before putting it in cloud. Hope this helps.