Работа с Yandex IoT Core на языке Java
В этом сценарии вы узнаете, как подключиться к Yandex IoT Core с помощью библиотеки Paho
Примечание
Исходный код, который используется в этом сценарии, доступен на GitHub
После подключения вы сможете:
Чтобы подключиться к Yandex IoT Core и начать обмен сообщениями:
- Создайте необходимые ресурсы Yandex IoT Core:
- Подключитесь к Yandex IoT Core.
- Аутентифицируйтесь в Yandex IoT Core:
- Установите соединение.
- Подпишитесь на топик и получайте сообщения.
- Отправьте сообщение.
- Завершите соединение.
Перед началом работы
- Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
- Скачайте и установите Java Development Kit
.
Создайте необходимые ресурсы Yandex IoT Core
Создайте реестр и добавьте ему сертификат
Если у вас уже есть сертификат, начните со второго шага.
-
Создайте сертификат для реестра:
openssl req -x509 \ -newkey rsa:4096 \ -keyout registry-key.pem \ -out registry-cert.pem \ -nodes \ -days 365 \ -subj '/CN=localhost' -
Создайте реестр:
yc iot registry create --name my-registry -
Добавьте сертификат реестру:
yc iot registry certificate add \ --registry-name my-registry \ # Имя реестра. --certificate-file registry-cert.pem # Путь к публичной части сертификата.
Создайте устройство и добавьте ему сертификат
Если у вас уже есть сертификат, начните со второго шага.
-
Создайте сертификат для устройства:
openssl req -x509 \ -newkey rsa:4096 \ -keyout device-key.pem \ -out device-cert.pem \ -nodes \ -days 365 \ -subj '/CN=localhost' -
Посмотрите список реестров, в которых можно создать устройство, или создайте новый реестр.
-
Создайте устройство:
yc iot device create --registry-name my-registry --name my-device -
Добавьте сертификат устройству:
yc iot device certificate add \ --device-name my-device \ # Имя устройства. --certificate-file device-cert.pem # Путь к публичной части сертификата.
Подключитесь к Yandex IoT Core
Перед подключением настройте параметры соединения connOpts с помощью следующего кода:
String clientId = "YandexIoTCoreTestJavaClient";
int keepAliveInterval = 60;
MqttClient client = new MqttClient("ssl://mqtt.cloud.yandex.net:8883", clientId);
// Установка обработчика асинхронных событий
client.setCallback(listener);
// Настройка параметров соединения.
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setKeepAliveInterval(keepAliveInterval);
Где:
MqttClient— класс, в котором указываются параметры подключения к Yandex IoT Core:- Адрес и порт.
- Идентификатор клиента.
MqttConnectOptions— класс для установки параметров соединения. Вы можете оставить настройки по умолчанию, но рекомендуется задать параметрkeepAliveInterval. От его значения зависит частота отправки командPINGREQ. Чем меньше значениеkeepAliveInterval, тем быстрее клиент понимает, что соединение было разорвано нештатным путем. Но для этого чаще отправляются тарифицируемые командыPINGREQ.listener— класс, реализующий интерфейсMqttCallback. Он используется для обработки событий о потере связи с сервером (connectionLost), доставке сообщения (deliveryComplete) и получении нового сообщения (messageArrived).
Аутентифицируйтесь в Yandex IoT Core
Есть два способа аутентификации:
Аутентификация с помощью сертификатов
При аутентификации с помощью X.509-сертификатов используются сертификаты в формате PKCS#12
openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12
Структура файлов
В примере, доступном на GitHub
/my_registry Директория реестра |текущая директория|. Пример нужно запускать из этой директории.
`- /device Директория устройства |device|.
| `- cert.pem Сертификат устройства в PEM-формате.
| `- key.pem Ключ устройства в PEM-формате.
| `- keystore.p12 Сертификат и ключ устройства в PKCS#12-формате.
`- cert.pem Сертификат реестра в PEM-формате.
`- key.pem Ключ реестра в PEM-формате.
`- keystore.p12 Сертификат и ключ реестра в PKCS#12-формате.
Загрузка сертификатов
Сертификат удостоверяющего центра задан в виде статической переменной TRUSTED_ROOT.
Для загрузки сертификатов в примере используется метод:
private SSLSocketFactory getSocketFactoryWithCerts(String certsDir)
Загрузка сертификатов происходит в несколько этапов:
-
Загрузите сертификат, используемый для аутентификации сервера:
// Загрузка сертификата удостоверяющего центра из статической переменной `TRUSTED_ROOT`. InputStream is = new ByteArrayInputStream(TRUSTED_ROOT.getBytes(StandardCharsets.UTF_8)); CertificateFactory cFactory = CertificateFactory.getInstance("X.509"); X509Certificate caCert = (X509Certificate) cFactory.generateCertificate(is); // Использование сертификата удостоверяющего центра для аутентификации сервера. KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType()); tks.load(null); tks.setCertificateEntry("caCert", caCert); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(tks); -
Загрузите сертификат клиента, используемый для аутентификации на сервере, из файла
keystore.p12:final char[] emptyPassword = "".toCharArray(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream(Paths.get(certsDir, "keystore.p12").toString()), emptyPassword); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, emptyPassword); -
Получите экземпляр класса
SSLSocketFactory:SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
После чего полученный выше экземпляр sslSocketFactory нужно передать в параметры соединения:
connOpts.setSocketFactory(sslSocketFactory);
Аутентификация по логину и паролю
Так как при аутентификации по логину и паролю Yandex IoT Core требует TLS-протокол, то необходимо загрузить сертификат, используемый для аутентификации сервера:
//Загружаем сертификат удостоверяющего центра из статической переменной `TRUSTED_ROOT`.
private SSLSocketFactory getSocketFactory()
throws Exception {
InputStream is = new ByteArrayInputStream(TRUSTED_ROOT.getBytes(StandardCharsets.UTF_8));
CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cFactory.generateCertificate(
is);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
tks.load(null); // Вам не нужно загружать из файла экземпляр класса `KeyStore`.
tks.setCertificateEntry("caCert", caCert);
tmf.init(tks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
return ctx.getSocketFactory();
}
В настройках соединения укажите логин (идентификатор реестра или устройства) и пароль:
connOpts.setUserName(login.trim());
connOpts.setPassword(password.trim().toCharArray());
и sslSocketFactory, получаемый из кода выше:
SSLSocketFactory sslSocketFactory = getSocketFactory();
connOpts.setSocketFactory(sslSocketFactory);
Установите соединение
Установите соединение с Yandex IoT Core с помощью метода:
client.connect(connOpts);
Метод connect является блокирующим. Выход из него происходит после завершения процесса установки соединения.
Для обработки события о потере связи с сервером вы можете использовать метод connectionLost интерфейса MqttCallback:
@Override
public void connectionLost(Throwable cause) {
}
При этом установить обработчик событий (с помощью метода setCallback) необходимо до вызова метода connect:
client.setCallback(listener);
...
client.connect(connOpts);
...
Где listener — класс, реализующий интерфейс MqttCallback.
Подпишитесь на топик и получайте сообщения
Подпишитесь на топик с помощью следующего кода. В методе subscribe нужно указать топик topic, на который вы хотите подписаться, и уровень качества обслуживания qos.
client.subscribe(topic, qos);
Для обработки события о получении нового сообщения вы можете использовать метод messageArrived интерфейса MqttCallback:
@Override
public void messageArrived(String topic, MqttMessage message){
}
При этом установить обработчик событий (с помощью метода setCallback) необходимо до вызова метода connect:
client.setCallback(listener);
...
client.connect(connOpts);
...
Где listener — класс, реализующий интерфейс MqttCallback.
Также для обработки события о получении нового сообщения вы можете использовать метод messageArrived интерфейса IMqttMessageListener:
client.subscribe(topic, qos, messageListener);
Где messageListener — класс, реализующий интерфейс IMqttMessageListener.
Отправьте сообщение
Отправьте сообщение с помощью следующего кода. В методе publish нужно указать топик topic, в который вы хотите отправить сообщение, и текст сообщения с помощью класса MqttMessage. При необходимости можно указать желаемый уровень качества обслуживания qos для экземпляра класса MqttMessage.
MqttMessage msg = new MqttMessage(message);
msg.setQos(qos);
client.publish(topic, msg);
Для обработки события о доставке сообщения вы можете использовать метод deliveryComplete интерфейса MqttCallback:
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
При этом установить обработчик событий (с помощью метода setCallback) необходимо до вызова метода connect:
client.setCallback(listener);
...
client.connect(connOpts);
...
Где listener — класс, реализующий интерфейс MqttCallback.
Завершите соединение
Завершите соединение с Yandex IoT Core с помощью методов:
client.disconnect();
client.close();
Где:
- Метод
disconnectзакрывает соединение с сервером. - Метод
closeосвобождает ресурсы классаMqttClient.