IOT hub message processor - azure

Having some trouble processing messages created in the Azure IoT Hub.
Getting the following eror: Exception thrown: 'Microsoft.ServiceBus.Messaging.Amqp.AmqpException' in Microsoft.ServiceBus.dll ("An AMQP error occurred (condition='amqp:link:redirect').")
Can anyone point me in the right direction?
Regards,
Jonas
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ServiceBus.Messaging;
namespace IOTHubMessageProcessor
{
class Program
{
static string connectionString = "HostName=yaddaaaa.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=keydataasdss+tacsCxwkWQeUm9sMCc2GHnQkIZHM=";
static string iotHubD2cEndpoint = "messages/events";
static EventHubClient eventHubClient;
static void Main(string[] args)
{
Console.WriteLine("Receive messages\n");
eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint);
var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds;
foreach (string partition in d2cPartitions)
{
ReceiveMessagesFromDeviceAsync(partition);
}
Console.ReadLine();
}
private async static Task ReceiveMessagesFromDeviceAsync(string partition)
{
var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow);
while (true)
{
EventData eventData = await eventHubReceiver.ReceiveAsync();
if (eventData == null) continue;
string data = Encoding.UTF8.GetString(eventData.GetBytes());
Console.WriteLine(string.Format("Message received. Partition: {0} Data: '{1}'", partition, data));
}
}
}
}

I don't encounter this issue when testing with your code, so it might be related to something else. I find the duplicate thread Azure IoT hub basic receiving example, AMQP error, it suggests check on block port or proxy settings, you can try it.

Your iotHubD2cEndpoint has an incorrect format. You can find your compatible endpoint in your azure portal -> messages -> device to cloud settings.
I found this a very helpful example: https://github.com/ppatierno/codesamples/tree/master/IoTHubAmqp/IoTHubAmqp

Code looks fine to me. Mine is identical and works well.
Your best bet is to create a new IoT hub in Azure and replace the strings.

While building the connectionstring, can you try "Endpoint=" instead of "HostName=" on line 12?
Hope this helps!
Mert

A couple of comments:
Please ensure that you are using the latest version of the Service Bus dll. i.e., 3.1.7 (as of today).
Please do not mix async and sync method calls in your code.
Let us know if you are still encountering this issue.

Sometimes I see that the proxy filters amqp packets. Changing the transport type to http probably will solve the problem.
Now I don't have access to Visual Studio but I seem to remember that it is possible to set the transport under the client properties.
If you try it you can easily find if the problem is in the proxy or in the program.

Related

My Azure Function Intermittantly fails to read the connection string

I have an azure function that runs off of a queue trigger. The repository has method to grab the connection string from the ConnectionStrings collection.
return System.Configuration.ConfigurationManager.ConnectionStrings["MyDataBase"].ToString();
This works great for the most part but I see intermittently that this returns a null exception error.
Is there a way I can make this more robust?
Do azure functions sometimes fail to get the settings?
Should I store the setting in a different section?
I also want to say that this runs thousands of times a day but I see this popup about a 100 times.
Runtime version: 1.0.12299.0
Are you reading the configuration for every function call? You should consider reading it once (e.g. using a Lazy<string> and static) and reusing it for all function invocations.
Maybe there is a concurrency issue when multiple threads access the code. Putting a lock around the code could help as well. ConfigurationManager.ConnectionStrings should be tread-safe, but maybe it isn't in the V1 runtime.
A similar problem was posted here, but this concerned app settings and not connection strings. I don't think using CloudConfigurationManager should be the correct solution.
You can also try putting the connection string into the app settings, unless you are using Entity Framework.
Connection strings should only be used with a function app if you are using entity framework. For other scenarios use App Settings. Click to learn more.
(via Azure Portal)
Not sure if this applies to the V1 runtime as well.
The solution was to add a private static string for the connection string. Then only read from the configuration if it fails. I then added a retry that paused half a second. This basically removed this from happening.
private static string connectionString = String.Empty;
private string getConnectionString(int retryCount)
{
if (String.IsNullOrEmpty(connectionString))
{
if (System.Configuration.ConfigurationManager.ConnectionStrings["MyEntity"] != null)
{
connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MyEntity"].ToString();
}
else
{
if (retryCount > 2)
{
throw new Exception("Failed to Get Connection String From Application Settings");
}
retryCount++;
getConnectionString(retryCount);
}
}
return connectionString;
}
I don't know if this perfect but it works. I went from seeing this exception 30 times a day to none.

How to Send Events from Linux Machine to Azure IoT Edge Hub

I have successfully deployed my first IoT Edge Device to Azure IoT Hub. The edge device is Ubuntu 16.04 I used the following link as a guide https://learn.microsoft.com/en-us/azure/iot-edge/quickstart-linux
The link uses tempSensor to generator realtime streaming data.
On my Ubuntu I have installed a realtime event stream generator of json using the following link http://acesinc.net/introducing-a-streaming-json-data-generator/
When I check the logs see events on my Ubuntu machine I can see the logs from the tempSensor but I can't see the events from my streaming event generator.
The problem is I can see the logs (traffic being generatored) from the tempSensor, however I can't see the traffic being generated from my realtime traffic.
I did some research and I discovered that in order to send events to the edge hub I would need to create a custom module that receives a message and send it to the Edge Hub. I therefore would need to modify the streaming generator to a module SDK to send the data. It was suggested that I follow the guide at the following link:
https://learn.microsoft.com/en-us/azure/iot-edge/tutorial-csharp-module
Now, the problem is the guide from link is based on simulated IoT edge device that uses data generator based on the tempSensor. Whereas my Ubuntu uses totally different generator. So I attempted to only as much from the guide that I think would enable to me get my Ubuntu to send events to the IoT Edge hub.
My configuration is as follows:
namespace mycsharpmodule4 {
using System.Collections.Generic; // for KeyValuePair<>
using Microsoft.Azure.Devices.Shared; // for TwinCollection
using Newtonsoft.Json; // for JsonConvert
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;
using Microsoft.Azure.Devices.Client.Transport.Mqtt;
class MessageBody {
public Machine machine {get;set;}
public Ambient ambient {get; set;}
public string timeCreated {get; set;} } class Machine { public double temperature {get; set;}
} class Ambient { public double temperature {get; set;} public int humidity {get; set;} }
}
Just so you know, I have followed everything in guide:
https://learn.microsoft.com/en-us/azure/iot-edge/tutorial-csharp-module
When I try build the code by running the command, 'Build IoT Edge Solution' I get the following error:
CSC : error CS5001: Program does not contain a static 'Main' method suitable for an entry point [C:\app\mycsharpmodule4.csproj]
The command 'cmd /S /C dotnet publish -c Release -o out' returned a non-zero code: 1
See image for complete view of error in Visual Studio Code.
visualstudiocode
Can someone let me know where I'm going wrong.
I'm checked on Stack Exchange for similar questions and came across
How to send data from a device to IOT HUB? . However, I was unable to make it work for me.
I have been at this for nearly 7 days now, and I'm about to give up.
Any help would be greatly appreciated
Paul

Polling storage queue for messages using console app webjob

I wanted to create a console app as a WebJob using .NET Core but the WebJobs SDK is not yet available in .NET Core.
I've been advised to handle the scenario of reading messages from Azure Storage Queue manually. Looks like all the WebJobs SDK does is to keep polling the queue anyway.
Is the following code the basic idea in doing this? It doesn't look very sophisticated but not sure how it can be more sophisticated.
static void Main(string[] args)
{
var runContinuously = true;
while (runContinuously)
{
ReadAndProcessMessage();
System.Threading.Thread.Sleep(1000);
};
}
private static void ReadAndProcessMessage()
{
// Read message
ReadMessage();
// Process message and handle the work
HandleWork();
}
That will work. And I like simplicity.
The QueueTriggerAttribute makes use of a random exponential back-off algorithm to help minimize your transaction costs. If you'd like to trace through the logic of how this is accomplished, starting with the QueueListener class is a good way to go. Clone the project and then hop over to the RandomizedExponentialBackoffStrategy class.

No job functions found in Azure Webjobs

Trying to get Azure Webjobs to react to incoming Service Bus event, Im running this by hitting F5. Im getting the error at startup.
No job functions found. Try making your job classes and methods
public. If you're using binding extensions (e.g. ServiceBus, Timers,
etc.) make sure you've called the registration method for the
extension(s) in your startup code (e.g. config.UseServiceBus(),
config.UseTimers(), etc.).
My functions-class look like this:
public class Functions
{
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static void ProcessQueueMessage([ServiceBusTrigger("test-from-dynamics-queue")] BrokeredMessage message, TextWriter log)
{
log.WriteLine(message);
}
}
I have every class and method set to public
I am calling config.UseServiceBus(); in my program.cs file
Im using Microsoft.Azure.WebJobs v 1.1.2
((Im not entirely sure I have written the correct AzureWebJobsDashboard- and AzureWebJobsStorage-connectionstrings, I took them from my only Azure storage-settings in Azure portal. If that might be the problem, where should I get them ))
According to your mentioned error, it seems that you miss parameter config for ininitializing JobHost. If it is that case, please use the following code.
JobHost host = new JobHost(config)
More detail info about how to use Azure Service Bus with the WebJobs SDK please refer to the document.The following is the sample code from document.
public class Program
{
public static void Main()
{
JobHostConfiguration config = new JobHostConfiguration();
config.UseServiceBus();
JobHost host = new JobHost(config);
host.RunAndBlock();
}
}

topicClient.Send timeout exception

I have a topicClient created from messagingfactory using connectionString
MessagingFactory.CreateFromConnectionString(connectionString)
MessagingFactory.CreateQueueClient(topicName).
In low band networks i get a timeout exception when sending messages to Azure Topic. Is there a way to change the timeout property?
I know there is a way when we use MessagingFactory.Create() method.
Thanks in advance
Here's the Code Snippet:
MessagingFactorySettings settings = new MessagingFactorySettings {
settings.OperationTimeout = TimeSpan.FromSeconds(120)
};
MessagingFactory messagingFactory = MessagingFactory.Create(connection, settings);
and more over - if you need performance critical messaging - ServiceBus also supports the standard Protocol for Messaging - AMQP.
settings.TransportType = TransportType.Amqp;
BTW, I guess a typo, but just in case - in your code snippet use : CreateTopicClient (not createQueueClient)
Hope it helps!
Sree
For those of you who stumbled here through google. I got a similar problem while using the 'Microsoft.Azure.ServiceBus' package in .NET core. I got a time out error when trying
await client.SendAsync(message);
In my case the problem was that my company was blocking port 5671.
Switching to AmqpWebSockets resolved my issue.
Put this after your connection string.
;TransportType=AmqpWebSockets

Resources