Working with Yandex IoT Core in C#
In this scenario, you'll learn how to connect to Yandex IoT Core using the Paho
Note
Once connected, you can:
To connect to Yandex IoT Core and start messaging:
- Create the required Yandex IoT Core resources:
- Connect to Yandex IoT Core.
- Authenticate in Yandex IoT Core:
- Establish a connection.
- Subscribe to a topic and receive messages.
- Send a message.
- Terminate the connection.
Getting started
- If you do not have the Yandex Cloud command line interface yet, install and initialize it.
- Download and install a development environment for .Net, e.g., Microsoft Visual Studio
.
Create the required Yandex IoT Core resources
Create a registry and add a certificate to it
If you already have a certificate, start with the second step.
-
Create a certificate for the registry (skip this step if you already have a registry certificate):
openssl req -x509 \ -newkey rsa:4096 \ -keyout registry-key.pem \ -out registry-cert.pem \ -nodes \ -days 365 \ -subj '/CN=localhost'
-
Create a registry:
yc iot registry create --name my-registry
-
Add a certificate to the registry:
yc iot registry certificate add \ --registry-name my-registry \ # Registry name. --certificate-file registry-cert.pem # Path to the public part of the certificate.
Create a device and add a certificate to it
If you already have a certificate, start with the second step.
-
(optional) Create a certificate for the device:
openssl req -x509 \ -newkey rsa:4096 \ -keyout device-key.pem \ -out device-cert.pem \ -nodes \ -days 365 \ -subj '/CN=localhost'
-
Review a list of the registries where you can create a device or create a new registry.
-
Create a device:
yc iot device create --registry-name my-registry --name my-device
-
Add a certificate to the device:
yc iot device certificate add \ --device-name my-device \ # Device name. --certificate-file device-cert.pem # Path to the public part of the certificate.
Connect to Yandex IoT Core
Before connecting, configure the connection parameters using the following code:
// Setting up a TLS connection
MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters
{
SslProtocol = SslProtocols.Tls12,
UseTls = true
};
// Enabling the server validation event handler
tlsOptions.CertificateValidationCallback += CertificateValidationCallback;
// Setting up the connection parameters
var options = new MqttClientOptionsBuilder()
.WithClientId($"Test_C#_Client_{Guid.NewGuid()}")
.WithTcpServer(MqttServer, MqttPort)
.WithTls(tlsOptions)
.WithCleanSession()
.WithCredentials(id, password)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(90))
.WithKeepAliveSendInterval(TimeSpan.FromSeconds(60))
.Build();
var factory = new MqttFactory();
IMqttClient mqttClient = factory.CreateMqttClient();
// Enabling the data receipt event handler
mqttClient.UseApplicationMessageReceivedHandler(DataHandler);
// Enabling the event handler for connections to Yandex IoT Core
mqttClient.UseConnectedHandler(ConnectedHandler);
// Enabling the event handler for losing connections to Yandex IoT Core
mqttClient.UseDisconnectedHandler(DisconnectedHandler);
Where:
MqttClientOptionsBuilderTlsParameters
is a class that specifies the parameters for using TLS when connecting to Yandex IoT Core.MqttClientOptionsBuilder
is a constructor class for setting connection options. You can use the default settings, but we recommend setting theWithKeepAlivePeriod
andWithKeepAliveSendInterval
parameters. The values of these parameters determine:-
The frequency of sending
PINGREQ
commands. -
The client's response time to a broken connection.
The lower the values of these parameters, the faster the client realizes that a connection terminated abnormally. However, this increases the frequency of sending payable
PINGREQ
commands.
-
Authenticate in Yandex IoT Core
There are two authentication methods:
Authentication using certificates
When authenticating with X.509 certificates, it is most convenient to use PKCS#12
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem
To load certificates in your project, use the following code:
X509Certificate2 certificate = new X509Certificate2(certPath);
The client certificate used for authentication on the server is specified when setting up a TLS connection:
X509Certificate2 certificate = new X509Certificate2(certPath);
List<byte[]> certificates = new List<byte[]>();
certificates.Add(certificate.Export(X509ContentType.SerializedCert));
// Setting up a TLS connection
MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters
{
Certificates = certificates,
SslProtocol = SslProtocols.Tls12,
UseTls = true
};
The certificate used for server authentication is used in the server validation event handler:
private static X509Certificate2 rootCrt = new X509Certificate2("rootCA.crt");
private static bool CertificateValidationCallback(X509Certificate cert, X509Chain chain, SslPolicyErrors errors, IMqttClientOptions opts)
{
try
{
if (errors == SslPolicyErrors.None)
{
return true;
}
if (errors == SslPolicyErrors.RemoteCertificateChainErrors)
{
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.ExtraStore.Add(rootCrt);
chain.Build((X509Certificate2)rootCrt);
// Comparing certificate thumbprints
var res = chain.ChainElements.Cast<X509ChainElement>().Any(a => a.Certificate.Thumbprint == rootCrt.Thumbprint);
return res;
}
}
catch { }
return false;
}
Authenticating by username and password
Authentication with a username and password in Yandex IoT Core requires the TLS protocol. To do this, use the MqttClientOptionsBuilderTlsParameters
class:
// Setting up a TLS connection
MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters
{
SslProtocol = SslProtocols.Tls12,
UseTls = true
};
// Enabling the server validation event handler
tlsOptions.CertificateValidationCallback += CertificateValidationCallback;
In the connection settings, using the WithCredentials
method, set the username to id
(registry or device ID) and the password
to password:
// Setting up the connection parameters
var options = new MqttClientOptionsBuilder()
.WithClientId($"Test_C#_Client_{Guid.NewGuid()}")
.WithTcpServer(MqttServer, MqttPort)
.WithTls(tlsOptions)
.WithCleanSession()
.WithCredentials(id, password)
.WithKeepAlivePeriod(TimeSpan.FromSeconds(90))
.WithKeepAliveSendInterval(TimeSpan.FromSeconds(60))
.Build();
Establish a connection
Establish a connection to Yandex IoT Core using the following code:
mqttClient.ConnectAsync(options, CancellationToken.None);
Subscribe to a topic and get messages
Use a callback function to receive messages:
...
mqttClient.UseApplicationMessageReceivedHandler(DataHandler);
...
private Task DataHandler(MqttApplicationMessageReceivedEventArgs arg)
{
return Task.CompletedTask;
}
Subscribe to a topic using the following code. In the SubscribeAsync
method, specify the topic
that you want to subscribe to and the level of quality of service (QoS
).
mqttClient.SubscribeAsync(topic, qos);
Send a message
Send a message using the following code. In the PublishAsync
method, specify the topic
that you want to send a message to, the message text, and the desired level of quality of service (qos
).
mqttClient.PublishAsync(topic, "Your message text.", qos);
Handle connection loss events and track message delivery using callback functions:
...
mqttClient.UseConnectedHandler(ConnectedHandler);
mqttClient.UseDisconnectedHandler(DisconnectedHandler);
...
private Task ConnectedHandler(MqttClientConnectedEventArgs arg)
{
return Task.CompletedTask;
}
private static Task DisconnectedHandler(MqttClientDisconnectedEventArgs arg)
{
return Task.CompletedTask;
}
Terminate the connection
Disconnect from Yandex IoT Core using the following code:
mqttClient.DisconnectAsync();