I have successfully configured my Azure IoT Dev Kit MXChip and I am able to send the data to the IoT Hub. I have also created a logic app with a router in it to receive a mail when the temperature is more than expected and a SQL server to save the Stream Analytics Job data. Basically, I followed the tutorial and till this point, everything was working fine, now I am just creating a simulator device where I can simulate events as mentioned in this tutorial. But whenever I run the application, I am always getting an error as below.
Microsoft.Azure.Devices.Client.Exceptions.UnauthorizedException:
'CONNECT failed: RefusedNotAuthorized'
I am not sure what I am missing here though I understand it is an authentication issue, and I have already changed my Hub Uri and device key as mentioned in the tutorial.
private readonly static string s_iotHubUri = "";
// This is the primary key for the device. This is in the portal.
// Find your IoT hub in the portal > IoT devices > select your device > copy the key.
private readonly static string s_deviceKey = "";
I just figured out what is making this error. I thought the device id we can use here is just a dummy one as it is not mentioned in the tutorial, but not. So, I had two option,
To create a new IoT device in the IoT Hub with the device Id I used in the simulator app (test-device) and update the device id and the key in the app
Use the device Id available already
I just created a new test-device in the Hub.
private readonly static string s_myDeviceId = "test-device";
private readonly static string s_iotHubUri = "youriothubname.azure-devices.net";
private readonly static string s_deviceKey = "devicekey";
After doing that changes, everything was working fine as expected.
Related
I have a device in Azure IoT central that has been receiving data. How can I send its telemetry data to its Azure Digital Twin so that they are connected?
You first need to pass the data from Azure IoT Central device to a cloud end point such as Service Bus or Event Hub. You can create an Azure Function and trigger it based on the end point you passed the data to. Within the Azure function you can create the code to push data to the Azure Digitial Twins.
Refer the following resources for data export
Export IoT data to Service Bus
Export IoT Hub data to Event Hubs
Once you have the data routed, use either of the following resources based on your clod end point to build Azure function
Run an Azure function when a Service Bus queue or topic message is created
Respond to events send to Event Hub event stream
Once you have the data flow into the Azure function, before you push the data to the Azure Digital Twin, ensure you have a Model created on the Azure digital twin representing you IoT device data.
If you haven't already done so, refer the Upload a model section to create a Data model for your Azure Digital Twin. Once you have the data model created, you can create Azure Digital Twin either from the Azure Digital Twin explorer or though the code Create Azure Digital Twin.
Once you have the Digital Twin created, you can then push data from your Azure function you created earlier. Here is the code I have tested through ServiceBus Queue trigger.
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Azure;
using Azure.Core.Pipeline;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace RajIoTCentral.Function
{
public class RajIoTCentralServiceBusQueue
{
private static readonly HttpClient httpClient = new HttpClient();
private static string adtServiceUrl = "https://<yourdigitaltwinendpoint>.digitaltwins.azure.net";
[FunctionName("RajIoTCentralServiceBusQueue")]
public async Task RunAsync([ServiceBusTrigger("iotcentraldata", Connection = "RajIoTDataServiceBus_SERVICEBUS")] string myQueueItem, ILogger log)
{
log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(myQueueItem);
try
{
var temperature = deviceMessage["telemetry"]["temperature"];
var deviceId = "TemperatureSensor";
log.LogInformation($"Temperature is:{temperature.Value<double>()}");
var credentials = new DefaultAzureCredential();
DigitalTwinsClient client = new DigitalTwinsClient(
new Uri(adtServiceUrl), credentials, new DigitalTwinsClientOptions
{ Transport = new HttpClientTransport(httpClient) });
log.LogInformation($"ADT service client connection created.");
var updateTwinData = new JsonPatchDocument();
updateTwinData.AppendReplace("/Temperature", temperature.Value<double>());
await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
}
catch (Exception ex) { log.LogInformation("No temperature in the telemetry data"); }
}
}
}
In the above code, I am pushing the Temperature value I received from the Service Bus queue on to the Azure Digital Twin.
Please refer the following resources for more information on the above code and the approach
Ingest IoT Hub telemetry into Azure Digital Twins
Build out an end-to-end solution
A similar post has been addressed on the Microsoft Q&A forum in the past. Please refer the question here Unable to view result of pipeline which trasport a value from a sensor to digital twin
from Microsoft EventHub Java SDK examples (https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-java-get-started-send), these are the steps that needs to be taken to be able to consume messages from an Even-Hub via the java SDK :
1.Create a storage account
2.Create a new class called EventProcessorSample. Replace the placeholders with the values used when you created the event hub and storage account:
3.
String consumerGroupName = "$Default";
String namespaceName = "----NamespaceName----";
String eventHubName = "----EventHubName----";
String sasKeyName = "----SharedAccessSignatureKeyName----";
String sasKey = "----SharedAccessSignatureKey----";
String storageConnectionString = "----AzureStorageConnectionString----";
String storageContainerName = "----StorageContainerName----";
String hostNamePrefix = "----HostNamePrefix----";
ConnectionStringBuilder eventHubConnectionString = new ConnectionStringBuilder()
.setNamespaceName(namespaceName)
.setEventHubName(eventHubName)
.setSasKeyName(sasKeyName)
.setSasKey(sasKey);
There are several things i don't understand about this flow -
A. Why is a storage account required? Why does it needs to be created only when creating a consumer and not when creating the event hub itself?
B. What is 'hostNamePrefix' and why is it required?
C. More of a generalaztion of A, but i am failing to understand why is this flow so complicated and needs so much configuration. Event Hub is the default and only way of exporting metrics/monitoring data from Azure which is a pretty straightforward flow - Azure -> Event Hub -> Java Application. Am i missing a simpler way or a simpler client option?
All your questions are around consuming events from Event hub.
Why is a storage account required?
Read the event only once: Whenever your application will read event from event hub, you need to store the offset(identifier for the amount of event already read) value somewhere. The storing of this information is known as 'CheckPointing' and this information will be stored in Storage Account.
Read the events from starting everytime your app connects to it: In this case, your application will keep on reading the event from very beginning whenever it will start.
So, the storage account is required to store the offset value while consuming the events from event hub in case if you want to read event only once.
Why does it needs to be created only when creating a consumer and not
when creating the event hub itself?
As it depends upon the scenario, whether you want to read your events only once or every time your app starts and that's why storage account is not required while creating event hub.
What is 'hostNamePrefix' and why is it required?
As the name states 'hostNamePrefix', this is name for your host. The host means the application which is consuming the events. And it's a good practice to make use of GUID as a hostNamePrefix. HostNamePrefix is required by the event hub to manage the connection with the host. In case, if you have 32 partitions, and you have deployed 4 instances of your same application then 8 partition each will be assigned to your 4 different instances and that's where the host name helps the event hub to manage the information about the connection of the respective partitions to their host.
I will suggest you to read this article on event hub for clear picture of the event processor host.
I am trying to set up Translator with my MXChip but after I finish the deployment it says "No IOT Hub".
I believe this is because of I can not successfully complete "Config IoT Hub Connection String" step. Details of step in this tutorial
What I do in this step is
I open devkit-traslater\run.csx and fill (string subscriptionKey = "";
string deviceName = "";) with name and key1 of Translator I get from portal.azure.com
Then after this step I switch iot Kit into configuration mode.
Then I follow the steps Config Device Settings but I never receive "The configuration success notification popup bottom right corner once it's done."
I dont know what I am doing wrong here
When developing Azure Function thru Class Library approach (local development) I came across issue when using Even Hub compatible endpoint of IoTHub for triggering my function. This is set thru IoTHubTrigger attribute:
[FunctionName("IoTHubMessageProcessor")]
public static void Run([IoTHubTrigger("messages/events", Connection= "IoTHubReceiveEventsConnectionEndpoint")]EventData message, ILogger log)
When using provided connection string and messages/events endpoint I received error stating that "messaging entity could not be found".
Solution was to alter the connection string and include also Event Hub compatible name in connection string as an entity path so it looks like this:
Endpoint=sb://<Event hub-compatible endpoint>.servicebus.windows.net/;EntityPath=<Event Hub compatible name>;SharedAccessKeyName=<keyName>;SharedAccessKey=<key>"
Im working through this guide using Azure Functions to commit IoTHub messages to Azure storage. I'm at section 5d, where I need to create a new Service Bus Connection string for my function, but whatever I use, including the format in the guide:
Endpoint=<Event Hub-compatible endpoint>;SharedAccessKeyName=iothubowner;SharedAccessKey=<Primary key>
I get the error:
Not a valid service bus connection string.
I’ve tried using the Event Hub-compatible endpoint from my IoT hub endpoints and also the connection string –- primary key from the access policy for iothubowner but again it rejects it.
I then created a new service bus and used that connection (see my answer below and initial optimism!) but when I tried to edit the function I get a 404 toast notification:
Function ($DeviceDataToStorage) Error: The listener for function
'Functions.DeviceDataToStorage' was unable to start.
Microsoft.ServiceBus: The messaging entity 'Management operation
failed. status-code: 404, status-description: The messaging entity
'sb://{MY SERVICE BUS CONNECTION STRING WHICH WAS
ACCEPTED}/{EVENTHUBNAME}' could not be found..' could not be found.
Can anyone who has used Azure functions before advise what format this needs to be in or more importantly where exactly in the portal I can get this from?
Thought I figured it out, but I hadn't.
Here's what I thought worked, but it didn't
*
Its missing from the tutorial, but you need to manually create a new
service bus endpoint (see
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues)
and copy the CONNECTIONSTRING-PRIMARYKEY from the
RootManageSharedAccessKey policy of Shared Access Policies.
*
According to your description, I checked this issue. As Prepare for IoT Hub connection to read messages states that you need to construct the connection string for your IoT hub endpoint as follows:
Endpoint={Event Hub-compatible endpoint};SharedAccessKeyName=iothubowner;SharedAccessKey={Primary key}
Replace {Event Hub-compatible endpoint} with:
Replace {Primary key} with:
Not a valid service bus connection string.
I assumed that you encounter this error when you creating a new Event Hub connection as follows:
When you add new connection string for your Event Hub, it should look like as follows:
Note: I assumed that you have confused with Service Bus connection string and IoT Hub connection string.
Connection string for Service Bus:
Endpoint=sb://{your-servicebus-name}.servicebus.windows.net/;SharedAccessKeyName={SharedAccessKeyName};SharedAccessKey={SharedAccessKey}