Connect real device to Azure IoT Central using MQTT - azure

I'm fiddling around with Azure IoT central and I configured a device. Now I want to send data using MQTT from a real device (no code).
I can't seemed to find information if this is possible for IoT central.
For IoT hub I found: Azure Iot Hub MQTT
I want to use IoT Central because of the built-in dashboards. Those do not seem to exist for IoT hub.
If I can't send data directly to IoT central, is there a way to use the IoT hub devices in IoT central?

Azure IoT Central uses an IoT Hub in the background, so you can still connect to the public device endpoints using the MQTT protocol on port 8883.
To get the address of the hub you can use the script below on any machine based on the device information in the Azure IoT Central app (see the docs)
// npm install azure-iot-device azure-iot-device-mqtt azure-iot-provisioning-device-mqtt azure-iot-security-symmetric-key --save
"use strict";
// Use the Azure IoT device SDK for devices that connect to Azure IoT Central.
var iotHubTransport = require('azure-iot-device-mqtt').Mqtt;
var Client = require('azure-iot-device').Client;
var Message = require('azure-iot-device').Message;
var ProvisioningTransport = require('azure-iot-provisioning-device-mqtt').Mqtt;
var SymmetricKeySecurityClient = require('azure-iot-security-symmetric-key').SymmetricKeySecurityClient;
var ProvisioningDeviceClient = require('azure-iot-provisioning-device').ProvisioningDeviceClient;
var provisioningHost = 'global.azure-devices-provisioning.net';
var idScope = '{your Scope ID}';
var registrationId = '{your Device ID}';
var symmetricKey = ''{your Primary Key}';
var provisioningSecurityClient = new SymmetricKeySecurityClient(registrationId, symmetricKey);
var provisioningClient = ProvisioningDeviceClient.create(provisioningHost, idScope, new ProvisioningTransport(), provisioningSecurityClient);
provisioningClient.register((err, result) => {
if (err) {
console.log('Error registering device: ' + err);
} else {
console.log('Registration succeeded');
console.log('Assigned hub=' + result.assignedHub);
console.log('DeviceId=' + result.deviceId);
var connectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';SharedAccessKey=' + symmetricKey;
console.log(connectionString);
}
});
Output:
Registration succeeded
Assigned hub=iotc-xxx.azure-devices.net
DeviceId=xxx
HostName=xxx.azure-devices.net;DeviceId=xxx;SharedAccessKey=xxx=
In addition, as stated by Matthijs van der Veer, do note that IoT Central uses the Device Provisioning Service to enable your device to connect to an IoT hub. It assigns an IoT hub to the device when registering but if the device gets reassigned to a different hub, the device will lose connection.

Related

How can we set Proxy setting for Provisioning of Azure IOT device

We are using this repo : https://github.com/Azure/azure-iot-sdk-node
We are trying to setup a DPS service for Azure Iot hub, we want to setup proxy for Provisioning through X509, In the Sample code : "register_x509.js"
We are using "var Transport = require('azure-iot-provisioning-device-mqtt').MqttWs;" library. In that, there is function call "setTransportOptions" and we sending our proxy agent as a permeant there :
var transport = new Transport();
transport.setTransportOptions({webSocketAgent:new HttpsProxyAgent(process.env.HTTP_PROXY)})
var securityClient = new X509Security(registrationId, deviceCert);
var deviceClient = ProvisioningDeviceClient.create(
provisioningHost,
idScope,
transport,
securityClient
);
// Register the device. Do not force a re-registration.
deviceClient.register(function (err, result) {
if (err) {
console.log("error registering device: " + err);
} else {
console.log("registration succeeded");
console.log("assigned hub=" + result.assignedHub);
console.log("deviceId=" + result.deviceId);
}
the initial tunneling is not happening due to which the connection is fialing. We also saw in documentation, that Azure SDK has a proxy filter which automatically take Proxy variable from environment, we tried that as well but still same issue. Can anyone please suggest a way for this use case.
Error we received : UnhandledPromiseRejectionWarning: Error: socket hang up

How can I debug "CONNECT failed: RefusedNotAuthorized" in Azure IOT Hub

I am receiving the verbose error "CONNECT failed: RefusedNotAuthorized" when attempting to connect to Azure IOT Hub with thumbprint authorization. I am able to connect without issue when creating a device with symmetric key authorization. I've struggled with various google searches all weekend and am at a lose as to how to proceed with debugging.
I am successfully registering a device with my Azure IOT Hub, using the following code:
...
var certificate = certificateHelper.CreateSelfSignedCertificate(userRequest.DeviceID.ToString());
// connect to iot hub
var registryManager = RegistryManager.CreateFromConnectionString("[My Connection String]");
// define device
Device iotDevice = new Device(userRequest.DeviceID.ToString());
iotDevice.Authentication = new AuthenticationMechanism()
{
Type = AuthenticationType.SelfSigned,
X509Thumbprint = new X509Thumbprint()
{
PrimaryThumbprint = certificate.Thumbprint,
SecondaryThumbprint = certificate.Thumbprint
}
};
// register
try
{
iotDevice = await registryManager.AddDeviceAsync(iotDevice);
}
catch (DeviceAlreadyExistsException)
{
...
I am creating the self signed certificates with the following code:
public X509Certificate2 CreateSelfSignedCertificate(string subjectName)
{
var ecdsa = ECDsa.Create(); // generate asymmetric key pair
var req = new CertificateRequest("CN=" + subjectName, ecdsa, HashAlgorithmName.SHA256);
return req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
}
And finally I am trying to connect to the IOT hub from the following code:
X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(device.Certificate));
var deviceAuthentication = new DeviceAuthenticationWithX509Certificate(device.TestDeviceID.ToString(), cert);
IotHub = DeviceClient.Create(_hostname, deviceAuthentication, TransportType.Mqtt);
IotHub.OpenAsync().Wait();
If there is something simple that is incorrect great, I would love to know. But what I'm really interested in is how I can debug this. I assume there are logs for the IOT server that will give me more information about why it believes that the device is unauthorized. Where are they? Do I query the hub for them or set up something in the portal? I've spent all weekend banging my head against a generic error and while I've learned a lot more about certificates and the hub itself, I still get the error.

Connect React Native App to Azure IoT Service

I am fairly new to React Native, but I created a simple app that has a button and a text that changes when the button is clicked. However, I want to connect to the IoT hub and receive information from the hub.
I am having issues currently with the connection. Here is my code:
import React from 'react';
import {StyleSheet, Dimensions, Alert, Text, View, Image, Button} from 'react-native';
const { width, height } = Dimensions.get("window");
'use strict';
var iothub = require('azure-iothub');
var connectionString = 'connection string';
var Mqtt = require('azure-iot-device-mqtt').Mqtt;
var DeviceClient = require('azure-iot-device').Client
var Message = require('azure-iot-device').Message;
var client = DeviceClient.fromConnectionString(connectionString, Mqtt);
// Create a message and send it to the IoT hub every second
setInterval(function(){
// Simulate telemetry.
var temperature = 20 + (Math.random() * 15);
var message = new Message(JSON.stringify({
temperature: temperature,
humidity: 60 + (Math.random() * 20)
}));
// Add a custom application property to the message.
// An IoT hub can filter on these properties without access to the message body.
message.properties.add('temperatureAlert', (temperature > 30) ? 'true' : 'false');
console.log('Sending message: ' + message.getData());
// Send the message.
client.sendEvent(message, function (err) {
if (err) {
console.error('send error: ' + err.toString());
} else {
console.log('message sent');
}
});
}, 1000);
The above part is a Node.js code, but I want to use it in a React application. How do I use Node packages in React?
I am getting the following error: Could not connect to development server.
Thanks.
As in your other question, I would suggest you take a look at Azure IoT Starter Kit Companion, which is a sample React Native application that helps you get your IoT device connected to an IoT Hub on iOS, Android and Windows.
Hope it helps!
Small point, you should NOT publish your connection strings. This is a rather large security issue.
As mentioned in your other question, the Azure IoT Hub Device SDK needs a Node.js runtime, which does not exists within the React Native app.
There is a plugin called nodejs-mobile-react-native for React Native that brings in the Node.js runtime and enables you to run Node.js apps alongside your React Native application.
I have written a detailed blog post about this topic outlining the steps necessary to achieve this.

Sending Messages from Leaf Device Downstream device not being handled by IoT Edge running at Transparent Gateway

I have followed all the instruction for setting up a "Downstream Device" to send messages through IoT Edge running in Transparent Gateway. I believe my routing rules are correct, but my Function module is not receiving any of the Messages through the message flow.
These are the instruction I've followed:
https://learn.microsoft.com/en-us/azure/iot-edge/how-to-create-transparent-gateway-linux
I am using 2 Linxu VMs (ubuntu 16.04.5).
IoT Edge Transparent Gateway VM is configured with all the certs properly setup, configured and verified. I've been able to using the openssl tool from the
openssl s_client -connect {my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com:8883 -CAfile /certs/certs/azure-iot-test-only.root.ca.cert.pem -showcerts
Downstream device running on Linux VM with Certs installed and verified. My connection string is as follows:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
a. I have verified I get a successful verification of the SSL cert using the openssl tool.
b. I'm using the the following in my downstream device for my connection using the NodeJS SDK
var client = DeviceClient.fromConnectionString(connectionString, Mqtt);
c. I can see the messages showing up at the Azure IoT Hub in the Cloud, but I can't get my module running on the IoT Edge Transparent Gateway to be hit.
Here are my routing rules configured for the edgeHub as specified in "Routing messages from downstream devices" in the sample doc page.
This is what the example docs show:
{ "routes":{ "sensorToAIInsightsInput1":"FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/ai_insights/inputs/input1\")", "AIInsightsToIoTHub":"FROM /messages/modules/ai_insights/outputs/output1 INTO $upstream" } }
This is what my routing configuration is set to:
"routes": {
"downstreamBatterySensorToBatteryDataFunctionInput1": "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/BatteryDataFunctionModule/inputs/input1\")",
"BatteryDataFunctionModuleToIoTHub": "FROM /messages/modules/BatteryDataFunctionModule/outputs/* INTO $upstream"
}
** Note that I've used by "FROM /* WHERE NOT IS_DEFINED" and "FROM /messages/* WHERE NOT IS_DEFINED"
My module on the IoT Edge is setup as a Function. When I use the out of the box example where the simulator device is another module running on the IoT Edge, then my function is hit correctly. Its only when I'm trying to use a "Downstream Device" that the module is not being triggered.
I have enabled "Debug Logging for the IoT Edge Service" running on my Transparent Gateway.
This is the basic Run method for the Function module:
#r "Microsoft.Azure.Devices.Client"
#r "Newtonsoft.Json"
using System.IO;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
// Filter messages based on the temperature value in the body of the message and the temperature threshold value.
public static async Task Run(Message messageReceived, IAsyncCollector<Message> output, TraceWriter log)
{
How can I figure out how to get my Module running in IoT Edge to be hit/triggered from a Downstream device?
So, you say you are seeing messages show up in IoT Hub, but not in Edge... A couple of things:
you posted this as your connection string in your node app:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
Did you copy/paste this exactly? the reason I ask is that, between the shared access key and the word "GatewayHostName", you have an equals sign and not a semi-colon..
it should be:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key};GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
(note the ';' before GatewayHostName… if you really did have an equals sign there instead of a semicolon, there's no telling what kind of chaos that would cause :-)
Secondly, in your route, you call your module BatteryDataFunctionModule.. just want to make sure that module name is exact, including being case-sensitive. You probably know that, but don't want to assume..
Finally, if the two things above check out, can you add an addition debugging route that sends the 'incoming data' to IoTHub as well..
"FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream"
so we can make sure the messages are actually making it through iot edge.
There are 2 problems that needed to be addressed to get the Downstream Device to communication
Thanks to #Steve-Busby-Msft I needed to have a semi-colon (;) at the end of the SharedAccessKey and before the GatewayHostName
you posted this as your connection string in your node app: HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
The NodeJS application Downstream Device also has to load up the cert correctly at the 'Application level'.
Notice the section of code for
var edge_ca_cert_path = '[Path to Edge CA certificate]';
Node JS Downstream Application
'use strict';
var fs = require('fs');
var Protocol = require('azure-iot-device-mqtt').Mqtt;
// Uncomment one of these transports and then change it in fromConnectionString to test other transports
// var Protocol = require('azure-iot-device-http').Http;
// var Protocol = require('azure-iot-device-amqp').Amqp;
var Client = require('azure-iot-device').Client;
var Message = require('azure-iot-device').Message;
// 1) Obtain the connection string for your downstream device and to it
// append this string GatewayHostName=<edge device hostname>;
// 2) The edge device hostname is the hostname set in the config.yaml of the Edge device
// to which this sample will connect to.
//
// The resulting string should look like the following
// "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>;GatewayHostName=<edge device hostname>"
var connectionString = '[Downstream device IoT Edge connection string]';
// Path to the Edge "owner" root CA certificate
var edge_ca_cert_path = '[Path to Edge CA certificate]';
// fromConnectionString must specify a transport constructor, coming from any transport package.
var client = Client.fromConnectionString(connectionString, Protocol);
var connectCallback = function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
} else {
console.log('Client connected');
client.on('message', function (msg) {
console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
// When using MQTT the following line is a no-op.
client.complete(msg, printResultFor('completed'));
// The AMQP and HTTP transports also have the notion of completing, rejecting or abandoning the message.
// When completing a message, the service that sent the C2D message is notified that the message has been processed.
// When rejecting a message, the service that sent the C2D message is notified that the message won't be processed by the device. the method to use is client.reject(msg, callback).
// When abandoning the message, IoT Hub will immediately try to resend it. The method to use is client.abandon(msg, callback).
// MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message.
});
// Create a message and send it to the IoT Hub every second
var sendInterval = setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var temperature = 20 + (Math.random() * 10); // range: [20, 30]
var humidity = 60 + (Math.random() * 20); // range: [60, 80]
var data = JSON.stringify({ deviceId: 'myFirstDownstreamDevice', windSpeed: windSpeed, temperature: temperature, humidity: humidity });
var message = new Message(data);
message.properties.add('temperatureAlert', (temperature > 28) ? 'true' : 'false');
console.log('Sending message: ' + message.getData());
client.sendEvent(message, printResultFor('send'));
}, 2000);
client.on('error', function (err) {
console.error(err.message);
});
client.on('disconnect', function () {
clearInterval(sendInterval);
client.removeAllListeners();
client.open(connectCallback);
});
}
};
// Provide the Azure IoT device client via setOptions with the X509
// Edge root CA certificate that was used to setup the Edge runtime
var options = {
ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
};
client.setOptions(options, function(err) {
if (err) {
console.log('SetOptions Error: ' + err);
} else {
client.open(connectCallback);
}
});

Microsoft Azure Iot - Blob unrecognized extension

Hello stack community.
I'm trying to send a simple message from a device to the Iot Hub, and then store this message on Blob.
To do so:
on the IoT Hub, i created a Router with the following property:
level='storage';
on the IoT Hub, i created an endpoint;
Everything works fine, except i get this warning when i inspect the Blob through the Azure platform showing me some bad characters:
The file 'xxxxxxxxxxx' may not render correctly as it contains an unrecognized extension.
The snippet to send the message from the device to the IoT Hub is the following:
var temperature = 20 + (Math.random() * 15);
var humidity = 60 + (Math.random() * 20);
var data = JSON.stringify({ deviceId: 'myFirstNodeDevice', temperature: temperature, humidity: humidity });
var message = new Message(data);
message.properties.add('level','storage');
console.log("Sending message: " + message.getData());
client.sendEvent(message, printResultFor('send'));
I can't figure out what's the real problem. Thank you in advance!
I haven't seen that message in before. I think this could be caused on how the route was configured. Use the following link for the full setup and integration of OIT hub messages with Azure storage to blob containers: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-store-data-in-azure-table-storage

Resources