Уведомление об изменении состояния устройства
Уведомляет платформу умного дома об изменившемся состоянии устройств.
Пример ситуации, в которой отправляется текущий запрос: пользователь прошел мимо датчика движения, датчик сработал.
Исчерпывающий перечень событий, при которых отправка этого запроса обязательна, — в разделе Требования к уведомлениям.
Условие работы сервиса уведомлений
Уведомления принимаются, если навык был опубликован хотя бы один раз, включая приватную публикацию. На черновике навыка, который ни разу не публиковали, сервис уведомлений не работает — отлаживайте отправку уведомлений на опубликованном навыке. Подробнее см. в разделе Требования к уведомлениям.
Формат запроса
POST https://dialogs.yandex.net/api/v1/skills/{skill_id}/callback/state
Заголовки запроса
|
Параметр |
Описание |
Обязательный |
|
Authorization |
Авторизационный токен владельца навыка. |
Да |
|
Content-Type |
Формат передаваемых/отправляемых данных. Возможные значения: application/json. |
Да, в операциях с http-методом POST |
Формат тела запроса
{
"ts": Float,
"payload": {
"user_id": String,
"devices": [{
"id": String,
"status": String,
"capabilities": [
"<capability1>": Object,
"<capability2>": Object
...
],
"properties": [
"<property1>": Object,
"<property2>": Object
...
]
}]
}
}
|
Параметр |
Тип |
Описание |
Обязательный |
|
ts |
Float |
Время возникновения события в секундах, формат unix timestamp. Передается время наступления события, а не время отправки запроса. Подробнее — в разделе Требования к |
Да |
|
payload |
Object |
Объект с устройствами. |
Да |
Объект payload
|
Параметр |
Тип |
Описание |
Обязательный |
|
user_id |
String |
Идентификатор пользователя, который был передан в ответе на запрос Информация об устройствах пользователя. |
Да |
|
devices |
Array of objects |
Массив с устройствами, которые изменили свое состояние. Массив не должен быть пустым. |
Да |
Объект devices
|
Параметр |
Тип |
Описание |
Обязательный |
|
id |
String |
Идентификатор устройства. Должен быть уникален среди всех устройств производителя. |
Да |
|
status |
String |
Статус устройства. Допустимые значения:
Если устройство недоступно, в поле передается значение Примеры запросов при изменении статуса устройства: переход в offline, возврат в online. |
Да, если отсутствуют |
|
capabilities |
Array of objects |
Массив с информацией о новых состояниях умений устройств. Пустой массив изменением не считается. Если менять нечего, поле не передается. |
Да, если отсутствуют |
|
properties |
Array of objects |
Массив с информацией о новых состояниях свойств. Пустой массив изменением не считается. Если менять нечего, поле не передается. |
Да, если отсутствуют |
Объект capabilities
|
Параметр |
Тип |
Описание |
Обязательный |
|
<capability1> |
Object |
Описание нового состояния умения. Подробнее со списком доступных умений и их параметрами можно ознакомиться в разделе Об умениях. Формат описания нового состояния совпадает с форматом, который используется в ответе на запрос Информация о состояниях устройств пользователя. |
Нет |
|
<capability2> |
Object |
Описание нового состояния умения. Подробнее со списком доступных умений и их параметрами можно ознакомиться в разделе Об умениях. Формат описания нового состояния совпадает с форматом, который используется в ответе на запрос Информация о состояниях устройств пользователя. |
Нет |
Объект properties
|
Параметр |
Тип |
Описание |
Обязательный |
|
<property1> |
Object |
Описание нового состояния свойства. Подробнее со списком доступных свойств и их параметрами можно ознакомиться в разделе О свойствах. Формат описания нового состояния совпадает с форматом, который используется в ответе на запрос Информация о состояниях устройств пользователя. |
Нет |
|
<property2> |
Object |
Описание нового состояния свойства. Подробнее со списком доступных свойств и их параметрами можно ознакомиться в разделе О свойствах. Формат описания нового состояния совпадает с форматом, который используется в ответе на запрос Информация о состояниях устройств пользователя. |
Нет |
Что должно быть в объекте devices
В объекте каждого устройства из массива devices обязательно передать хотя бы одно из:
status— изменение доступности устройства (onlineилиoffline);- непустой массив
capabilities— изменение состояния умений; - непустой массив
properties— изменение показаний свойств.
Пустой массив изменением не считается. Если менять нечего, поле не передается.
Допускается запрос, содержащий только status, — например, при потере или восстановлении связи с устройством, когда состояние умений и свойств не изменилось.
Важно
Для устройств, у которых в ответе на запрос Информация об устройствах пользователя указано status_info.reportable: true, отправка поля status обязательна при каждом переходе доступности — как в offline, так и в online.
Требования к ts
Поле ts содержит время возникновения события, а не время отправки уведомления. Формат — unix timestamp в секундах (дробное число).
- Платформа использует
tsдля упорядочивания событий. Значениеtsдолжно быть монотонным для каждого устройства:tsпоследующего события не должен быть меньшеtsпредыдущего. - Если платформа получает уведомление с устаревшим
ts(меньшим, чем у уже обработанного события для того же устройства), такое событие игнорируется. - Не используйте
tsдля задержки отправки — событие отправляется по факту его наступления. - Часы на серверах провайдера должны быть синхронизированы. Значение
tsиз будущего приведет к тому, что последующие события будут отброшены как устаревшие.
Формат ответа
HTTP/1.1 202 Accepted
{
"request_id": String,
"status": "ok"
}
|
Параметр |
Тип |
Описание |
Обязательный |
|
request_id |
String |
Идентификатор запроса. Необходимо логировать для расследования инцидентов. |
Да |
|
status |
String |
Статус обработки запроса. Допустимые значения:
|
Да |
HTTP/1.1 400
{
"request_id": String,
"status": "error",
"error_code": String,
"error_message": String
}
|
Параметр |
Тип |
Описание |
Обязательный |
|
request_id |
String |
Идентификатор запроса. Необходимо логировать для расследования инцидентов. |
Да |
|
status |
String |
Статус обработки запроса. Допустимые значения:
|
Да |
|
error_code |
String |
Код ошибки. Допустимые значения:
|
Нет |
|
error_message |
String |
Сообщение об ошибке. |
Нет |
Обработка ошибок и повторные запросы
Навык должен обрабатывать ответ платформы на свой запрос в соответствии с таблицей ниже.
Принятое уведомление платформа подтверждает кодом 202 Accepted. Код 200 OK в ответ на запрос в сервис уведомлений не возвращается.
|
HTTP-код |
status |
error_code |
Что произошло |
Что делать |
|
|
|
— |
Уведомление принято в обработку |
Ничего. Повторять запрос не нужно |
|
|
|
|
Невалидный JSON или тело запроса не соответствует контракту: не передано ни одно из |
Повтор запроса в неизменном виде не даст результата — он будет отклонен снова. Исправьте формирование запроса на своей стороне |
|
|
|
|
Платформа не знает пользователя с таким |
Не повторять. Остановить отправку уведомлений для этого |
|
|
— |
— |
Не передан или истек OAuth-токен |
Обновить OAuth-токен для Диалогов и повторить запрос |
|
|
— |
— |
Владелец токена не является владельцем навыка |
Не повторять. Использовать токен пользователя Яндекса, который создал навык |
|
|
— |
— |
В пути запроса указан неверный |
Не повторять. Проверить идентификатор навыка |
|
|
— |
— |
Временная проблема на стороне платформы или сети |
Повторить запрос с нарастающей задержкой, сохранив исходное значение |
|
|
— |
— |
Прием уведомлений от навыка ограничен — платформа считает отправку нарушающей требования к уведомлениям |
Остановить отправку и устранить причину ограничения. Подробнее см. в разделе Ограничение приема уведомлений |
При повторной отправке не нужно:
- повторять запрос, отклоненный с
BAD_REQUESTилиUNKNOWN_USER, — он будет отклонен снова; - подставлять новое значение
ts— при повторе передается исходное время события; - отправлять уведомление об изменении, которого не было, — например, повторно отправлять последнее состояние по таймеру.
Если после нескольких повторов доставить событие не удалось, отправьте актуальное состояние устройства новым уведомлением с новым ts, а не копию устаревшего события.
Примеры
Переход в offline
curl -i -X POST 'https://dialogs.yandex.net/api/v1/skills/user-test-skill/callback/state' \ -H 'Authorization: OAuth 123qwe456a...' \ -H 'Content-Type: application/json' \ -d '{ "ts": 1602703322.1, "payload": { "user_id": "provider-user-id-1", "devices": [{ "id": "lamp-001", "status": "offline" }] } }'
HTTP/1.1 202 Accepted { "request_id": "75442486-0878-440c-9db1-a7006c25a39f", "status": "ok" }
Возврат в online
curl -i -X POST 'https://dialogs.yandex.net/api/v1/skills/user-test-skill/callback/state' \ -H 'Authorization: OAuth 123qwe456a...' \ -H 'Content-Type: application/json' \ -d '{ "ts": 1602703400.5, "payload": { "user_id": "provider-user-id-1", "devices": [{ "id": "lamp-001", "status": "online" }] } }'
HTTP/1.1 202 Accepted { "request_id": "a1b2c3d4-5678-90ef-1234-567890abcdef", "status": "ok" }
Изменение состояния умения
curl -i -X POST 'https://dialogs.yandex.net/api/v1/skills/user-test-skill/callback/state' \ -H 'Authorization: OAuth 123qwe456a...' \ -H 'Content-Type: application/json' \ -d '{ "ts": 1602703500.0, "payload": { "user_id": "provider-user-id-1", "devices": [{ "id": "lamp-001", "capabilities": [{ "type": "devices.capabilities.on_off", "state": { "instance": "on", "value": true } }] }] } }'
HTTP/1.1 202 Accepted { "request_id": "b2c3d4e5-6789-01ab-cdef-234567890abc", "status": "ok" }
Изменение состояния свойства
curl -i -X POST 'https://dialogs.yandex.net/api/v1/skills/user-test-skill/callback/state' \ -H 'Authorization: OAuth 123qwe456a...' \ -H 'Content-Type: application/json' \ -d '{ "ts": 1602703600.0, "payload": { "user_id": "provider-user-id-1", "devices": [{ "id": "sensor-001-snsr", "properties": [{ "type": "devices.properties.event", "state": { "instance": "motion", "value": "detected" } }] }] } }'
HTTP/1.1 202 Accepted { "request_id": "c3d4e5f6-7890-12ab-cdef-34567890abcd", "status": "ok" }
Одновременное изменение статуса и состояния
curl -i -X POST 'https://dialogs.yandex.net/api/v1/skills/user-test-skill/callback/state' \ -H 'Authorization: OAuth 123qwe456a...' \ -H 'Content-Type: application/json' \ -d '{ "ts": 1602703700.0, "payload": { "user_id": "provider-user-id-1", "devices": [{ "id": "lamp-001", "status": "online", "capabilities": [{ "type": "devices.capabilities.on_off", "state": { "instance": "on", "value": true } }], "properties": [{ "type": "devices.properties.float", "state": { "instance": "temperature", "value": 23.5 } }] }] } }'
HTTP/1.1 202 Accepted { "request_id": "d4e5f6a7-8901-23ab-cdef-4567890abcde", "status": "ok" }
Успешный ответ — 202 Accepted
HTTP/1.1 202 Accepted { "request_id": "75442486-0878-440c-9db1-a7006c25a39f", "status": "ok" }
Ответ с ошибкой
HTTP/1.1 400 { "request_id": "same-as-in-request", "status": "error", "error_code": "UNKNOWN_USER", "error_message": "User not found" }
Как обрабатывать ответ платформы, см. в разделе Обработка ошибок и повторные запросы.
Число с плавающей точкой с точностью до 6-9 десятичных знаков.
Cтрока, выделяется кавычками, например "Hello world".
Список пар "ключ": значение, разделенных запятой. Выделяется фигурными скобками {}.
{
"name": "John",
"surname": "Smith"
}
Массив элементов, разделенных запятой. Элементом могут быть стандартные элементы JSON: строка, число, true, false, объект или массив. Массив выделяется квадратными скобками []:
"cities": ["Moscow", "Tokyo", "New York"]
Идентификатор вызываемого навыка, присвоенный при создании.
Чтобы узнать идентификатор своего навыка, откройте его в консоли разработчика — идентификатор можно скопировать на вкладке Общие сведения, внизу страницы.