Данная статья позволит тем, кто еще только начинает свою разработку или уже применяет технологию NB-IoT, составить представление о том, как можно удаленно взаимодействовать с NB-IoT устройством.

image

Краткий обзор


NB-IoT легко наступает на пятки 2G и зарекомендовал себя как энергоэффективный стандарт сотовой связи, который уже в обозримом будущем будет способен потеснить укрепившийся на своей позиции 2G. Причиной тому является возможность гибко подойти к вопросу энергопотребления одной из самых потребляющих частей устройства – радиопередатчику. Если не вдаваться глубоко в детали, то вместе с NB-IoT у нас появилась возможность гибко настраивать режимы работы устройства за счет настройки расписания выхода устройства на связь и взаимодействия устройства с серверами в сети Интернет.

Параллельно с этим значительно увеличивается количество абонентских устройств одновременно подключенных к одной соте, равно как и затраты оператора сотовой связи на поддержание работоспособности самой этой связи.

Предполагается, что у читателя есть примерное представление о технологии NB-IoT и имеется минимальный опыт взаимодействия.

Сложности внутри сети NB-IoT


Вместе с возможностью управлять радиопередатчиком и высокой энергоэффективностью пришла проблема отправки данных в направлении от сервера к модулю (устройству). Причина в том, что обеспечить сотни тысяч устройств белыми IP адресами можно, но это влечет за собой большое количество накладных расходов и снижает общую надежность сети ввиду ее усложнения. Модуль получает адрес за NAT оператора и оператору сложно транслировать его «наружу» ввиду большого количества устройств. Например: 100 тысяч устройств это такое же количество IP адресов и в рамках IPv4 попросту не представляется возможным такое реализовать. Переход на IPv6 способен решить эту проблему, но все равно придется платить за «белый» адрес устройства в сети, что ощутимо ударит по карману корпоративных клиентов.

Т. е. в общем случае получается так, что устройство может работать только в одностороннем режиме передавая данные на сервер без возможности получения данных со стороны сервера ввиду того, что серверу практически неизвестно когда устройство первый раз выйдет на связь. Либо использовать в среднем не более пяти минут время после установления соединения устройства с сервером на передачу данных от сервера к устройству.

NIDD (Non-IP Data Delivery) – зачем это нужно?


В работе с сетью NB-IoT большую сложность представляет обратиться к устройству для передачи команды или неких данных, чтобы решить эту проблему был придуман механизм оптимизации передачи малых объемов данных – Non-IP Data Delivery (NIDD). Механизм уменьшает общий размер передаваемого сообщения за счет сокращения заголовков. Это, в свою очередь, положительно влияет на характеристики устройства: сокращает энергопотребление и увеличивает автономность (время работы от аккумулятора). В итоге отказ от поддержки IP ведет к удешевлению устройства, сокращению времени разработки, повышению конкурентоспособности на рынке IoT-устройств и т. д.

SCEF (Service Capability Exposure Function) – подарок для пользователей


SCEF – это функциональный элемент сети, впервые появившийся и 3GPP Release 13, развернутый на стороне оператора сотовой связи и предоставляющий безопасный канал связи между SCS/AS (Service Capability Server / Application Server) и NB-IoT устройством. SCEF обеспечивает канал коммуникации при общении с устройством по NIDD и предоставляет доступ к дополнительным сетевым возможностям/сервисам сети NB-IoT через единый интерфейс прикладного программирования (из описания API T8). В 3GPP Release 13 был стандартизирован только механизм взаимодействия SCEF с интерфейсами сотовой сети. Таким образом оптимизируется нагрузка на сеть, упрощается взаимодействие с устройством, упрощается алгоритм работы самого устройства. Также SCEF выполняет высокие требования к безопасности передачи данных и выполнение требований к подтверждению успешной передачи данных в обоих направлениях.

Что это значит на практике


SCEF позволяет абстрагироваться от сложных систем взаимодействия с NB-IoT устройством, в том числе когда последнее находится в режиме eDRX или PSM и недоступно для передачи данных в направлении сервер->устройство. Когда устройство получило регистрацию и «договорилось» с ядром сети оператора о расписании выхода на связь, используя простой интерфейс можно передавать данные устройству и получать данные от него, управлять «подпиской» своего устройства и AS на те или иные события, самостоятельно задавать и привязывать уникальные имена к универсальным идентификаторам External ID и многое другое. Все это через один и тот же интерфейс – API T8.

Важно отметить, что сервер (AS) может быть не один, а несколько и можно гибко настроить распределение информации между серверами по тем или иным событиям или группам устройств.

Как это работает


Самым популярным решением организации доступа устройства в сотовую сеть является использование модуля сотовой связи, например:


Такой модуль при регистрации в сотовой сети передает оператору некоторую информацию, в том числе IMSI абонентской СИМ-карты который оператор может привязать к абонентской учетной записи или сам абонент при наличии доступа к личному кабинету у оператора. За ширмой SCEF скрывается знание о следующем сеансе связи с устройством. Регистрация non-IP устройства в сети оператора возможна только при наличии хоть одной подписки от SCS/AS на это устройство. Нет подписки – никто не будет общаться с этим устройством по NIDD, а устройство не будет зарегистрировано в сети. Таким образом, SCEF, зная о следующем сеансе связи, способен передать данные с/на устройство, в соответствии с заданными параметрами доставки и времени жизни передаваемого сообщения, без необходимости организовывать дополнительный контроль состояния передачи данных и контроля доставки.

Легковесность


Инкапсуляция единиц байт данных от устройства в протокол TCP и передача на сервер дорого обходится в пересчете на сотни тысяч абонентских устройств в парке компании. SCEF позволяет отказаться от IP на устройстве и передача происходит только non-IP данных, без IP заголовков через сигнальный канал, что способствует кратному удешевлению стоимости переданного байта и предоставляет дополнительную выгоду от использования сервиса. Причем SCEF не привносит никаких изменений в передаваемые данные как на устройство, так и с него, payload передается прозрачно. Следовательно, используя NIDD можно передавать не только неструктурированные данные, но и данные «завернутые» в понятный стандартизированный формат, например JSON, для упрощения обработки данных на стороне AS.

Начало работы


Структура URI (Uniform Resource Identifier) на примере Postman


В первую очередь нужно получить от оператора доступ к Вашему личному кабинету (услуга М2М-менеджер). Для коммерческой реализации МТС предоставляется единый интерфейс Личный кабинет, где вы можете самостоятельно создавать APN, login/password доступа к API и присваивать имена ScsAsID, extID для своих устройств.

Т.е. нам как минимум потребуются:
  • ScsAsID – ID вашего AS
  • APN – тот, что обычно используется для взаимодействия с сетью не подойдет
  • Login/Password – данные для доступа в личный кабинет и взаимодействия с SCEF
  • URI –HTTP адрес и порт в сети предоставленного вам SCEF
  • externalID – ID нашего устройства


Переходим к практике


С теорией покончено, перейдем уже к самому интересному – практике на модуле производства SIMCom Wireless Solutions – SIM7020E.

Сначала нужно сконфигурировать сам модуль на работу с NIDD. Для этого нужно сначала перевести модуль в режим CFUN=0 и настроить его:

AT+CFUN=0
+CPIN: NOT READY

OK
AT+ENVDM=1,tel_conn_mgr,default_pdn_flag,1,30
OK

выключить модуль

AT+CPOWD=1
NORMAL POWER DOWN

включить и продолжить настройку

AT+CFUN=0
+CPIN: NOT READY

OK
AT*MCGDEFCONT="Non-IP","<APN>"
OK
AT+CFUN=1
OK
AT+NIDD=1, <APN>
OK

+CPIN: READY

причем нижнюю команду (AT+NIDD=1, <APN полученный от оператора>) нужно отправить как можно быстрее после того как будет получено ‘+CPIN: READY’.

AT+EGACT=1,4," <APN>","<login>","pass"
+EGACT:1

OK

проверяем регистрацию модуля в сети пакетной передачи данных.

AT+CGREG?
+CGREG: 0,1

OK

и активируем NIDD на модуле

AT+EGACT=1,4,"<APN>","<login>","<pass>"
+EGACT:1

OK

+EGACT:1,1,1,4

Готово. На этом этапе работа с модулем завершена. Перейдем к настройке SCEF.

Как вернуть вернуть все обратно
Модуль можно вернуть к обычному режиму работы всего лишь отправив в него две команды:

AT+CFUN=0
AT+ENVDM=1,tel_conn_mgr,default_pdn_flag,1,31

и перезагрузить.

SCEF


API T8


Существует специальный документ подробно описывающий взаимодействие с SCEF. Данное API определяет набор моделей данных, ресурсов и связанных с ними процедур для передачи данных, не связанных с IP.



Работа с SCEF и подписками на сервисы – JSON (JavaScript Object Notation)


Данные, включающие в себя настройку SCEF и передаваемые по протоколу HTTP/1.1 на SCEF, должны быть закодированы в формат JSON, а тело самого HTTP запроса в поле Content-Type должно включать заголовок “application/json”. При этом, если сообщение было доставлено получателю и получено подтверждение о доставке – SCEF должен удалить у себя соответствующую конфигурацию, отправить сообщение через HTTP POST для AS с кодом состояния «200 OK» и включить отчет о состоявшемся событии.

Postman


Не буду углубляться в то, как работать с данной утилитой, в Интернете можно найти массу обзоров. Скажу только, что она имеет некоторые ограничения в ее бесплатной версии, но нам много и не потребуется, поставляемого бесплатно функционала более чем достаточно для наших задач.

После того как мы ее загрузили и открыли нас поприветствует первая вкладка – Launchpad, где нам предложат создать наш первый запрос, не будем отказываться.


Сразу приступим к конфигурации нашего нового устройства.

Изначально у нас настроен метод GET, переключаем его на POST (чуть позже станет понятно зачем это нужно). На вкладке «Authorization» вводим имеющиеся у нас на руках «credentials»:


Теперь создадим наш первый запрос:


В теле запроса укажем:

{
    "externalId": "<ID устройства>",
    "reliableDataService": false,
    "pdnEstablishmentOption": "WAIT_FOR_UE",
    "duration":"2020-12-31T23:59:59Z",
    "notificationDestination": "http://<IP адрес>:<port>"
}

Важно!
Обратите внимание на:
  • “duration” – в случае указания в запросе duration большее чем регламентируется внутренними SLA SCEF для этого сервиса (SCSAS/ID) либо его отсутствия, SCEF укажет в ответе корректное, установленное для данной подписки
  • “maximumPacketSize” – максимальный размер в байтах для передачи с/на девайс

Давайте сразу отметим, что в “pdnEstablishmentOption” возможны следующие варианты:
  • WAIT_FOR_UE – буферизовать если устройство недоступно (не зарегистрировано в сети или в PSM или в другом состоянии)
  • INDICATE_ERROR – сразу ответить ошибкой, если устройство недоступно
  • SEND_TRIGGER – использовать сервис Device Triggering (альтернативный канал доставки через SMS). В данной статье не рассматривается.

Этот же параметр используется нами для отправки данных на устройство. А при создании подписки мы можем сразу отправить данные на устройство, сократив количество API запросов.
Все! Можно нажимать кнопку Send и внимательно изучить что же мы получим в ответ от SCEF:

{
    "externalId": "<ID устройства>",
    "duration": "2020-12-31T23:59:59Z",
    "notificationDestination": "http://<IP адрес>:<port>",
    “reliableDataService": false,
    "maximumPacketSize": 500,
    "self": "/3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>",
    "status": "ACTIVE"
}

В строке self нас интересует в первую очередь ID созданной нами конфигурации, терять его крайне нежелательно, т. к. скорее всего операторы не будут поддерживать функцию запроса всех созданных конфигураций. Когда будет несколько тысяч устройств, созданных в рамках одного ScsAsID, будет создаваться слишком большая нагрузка на серверы SCEF для трансляции всех конфигураций устройств. Берем за правило: одно устройство = одна подписка в рамках сервиса ScsAsID.

Таким образом мы уже можем принимать данные от модуля на сервере, IP адрес и порт которого мы указали выше.

Передача данных от модуля к AS


Попробуем передать данные от устройства к AS, вернемся к модулю SIM7020E и если мы его с предыдущей главы больше не трогали и не выключали отправим в него команду:

AT+NIDD=2,<APN>,1234567890abcdefghijklmnopqrstuvwxyz
OK

Практически сразу на сервере (AS), который является принимающей стороной увидим:

POST / HTTP/1.1
OCSGHTTPProcessor: 147ff7c6-a43d-4fc9-b303-0ca50f497747
X-callback-t8-type: 3
X-callback-url: http://<IP адресс>:<port>
X-api-network-service-node: 0
Content-Type: application/json
Content-Length: 200
Host: <IP адрес>:<port>
Connection: Keep-Alive
User-Agent: Apache-HttpAsyncClient/4.1.3 (Java/1.8.0_181)

{"externalId":"<ID устройства>","niddConfiguration":"/3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>","data":"1234567890abcdefghijklmnopqrstuvwxyz\r","reliableDataService":false}

Нужно отметить, что в данном случае передаваемая от модуля информация не хранится внутри SCEF и сразу же транслируется на наш сервер по протоколу HTTP.

Передача данных от AS к модулю


Для того чтобы отправить данные в направлении от нашего AS к модулю вернемся к Postman и создадим новый запрос используя метод POST:


Обратите внимание, что в поле «адрес» появилось дополнение, в котором мы указали для какой конфигурации мы хотим отправить сообщение. Если в нашу конфигурацию будет включено несколько устройств – можно воспользоваться идентификатором “externalGroupID” и тогда все они получат эти данные. Еще один важный момент – время жизни отправляемого сообщения, указывается в секундах и имеет достаточно широкий диапазон.

Кстати, если устройство в этот момент будет не в сети, то наше сообщение будет буферизовано на SCEF, а строка “maximumLatency” будет нам подсказывать сколько секунд осталось до того момента, как сообщение будет уничтожено если устройство до истечения заданного нами таймера не выйдет на связь. Ниже представлено как это будет выглядеть запрошенная текущая конфигурация SCEF (используется механизм GET, об этом будет ниже):

{
    "externalId": "<ID устройства>",
    "duration": "2020-12-31T23:59:59Z",
    "notificationDestination": "http://<IP адрес>:<port>",
    "reliableDataService": false,
    "status": "ACTIVE",
    "niddDownlinkDataTransfers": [
    {
        "externalId": "<ID устройства>",
        "reliableDataService": false,
        "data": "123498",
        "maximumLatency": 96,
        "priority": 1,
        "self": "/3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>/downlink-data-deliveries/1"
    }
}

Если по истечению таймера, устройство так и не вышло на связь – SCEF сообщит вашему серверу (AS), что сообщение не было доставлено по причине истечения таймера и сообщение будет удалено:

POST / HTTP/1.1
OCSGHTTPProcessor: 14c8cab8-ecce-4868-a59e-1f784224518b
X-callback-t8-type: 4
X-callback-url: http://<IP адресс>:<port>
X-api-network-service-node: 0
Content-Type: application/json
Content-Length: 139
Host: <IP адрес>:<port>
Connection: Keep-Alive
User-Agent: Apache-HttpAsyncClient/4.1.3 (Java/1.8.0_181)

{"niddDownlinkDataTransfer":"/3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>/downlink-data-deliveries/1","status":"FAILURE"}

При успешной SCEF сразу ответит:

{
    "externalId": "<ID устройства>",
    "reliableDataService": false,
    "status": "SUCCESS"
}

Можно добавить возможность приоритезации сообщений в случае их буферизации. Регулируется параметром “priority”. При отправке нового сообщения на устройство и при наличии превышения буфера доставки на SCEF, сообщение будет заменено на сообщение с меньшим приоритетом в противном случае сообщение не будет принято на доставку. Также есть возможность удалить сообщение из буфера.

Если сообщение не может быть доставлено, и оно положено в буфер – вы получите следующее:

{
    "externalId": "<ID устройства>",
    "reliableDataService": false,
    "self": "/3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>/downlink-data-deliveries/2",
    "status": "BUFFERING_TEMPORARILY_NOT_REACHABLE"
}

При последующих отправках в период недоступности устройства ответ будет следующий:

{
    "externalId": "<ID устройства>",
    "reliableDataService": false,
    "self": "3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>/downlink-data-deliveries/1",
    "status": "BUFFERING"
}

Важно!
Обратите внимание на:
/<ID конфигурации>/downlink-data-deliveries/1
Единица – это номер сообщения в буфере SCEF. Используя его, можно управлять данным сообщением. Он так же используется при получении нотификации о доставке.

Просто оставлю это здесь. Нотификация о доставке «забуферизированного» сообщения:

{
"niddDownlinkDataTransfer":"3gpp-nidd/v1/<ScsAsID>/configurations/<ID конфигурации>/downlink-data-deliveries/1",
"status":"SUCCESS"
}

Контроль за статусом состояния устройства возможен через другой сервис SCEF под названием «Monitoring Event (MONTE)». В рамках MONTE возможно получать нотификации о событиях и время (например, когда устройство станет доступно), использую аналогичную подписную систему. Но об этом поговорим в другой раз.

Получение конфигурации от SCEF


Наверное, вы обратили внимание, что можно получить текущую конфигурацию от SCEF. Давайте сделаем это. Берем уже полюбившийся нам Postman и создаем следующий запрос используя метод GET:


Т.е. тело самого сообщения оставляем пустым, а в строке адреса нам достаточно только указать ID созданной нам конфигурации, чтобы в ответ получить ее текущее состояние:

{
    "externalId": "<ID устройства>",
    "duration": "2020-12-31T23:59:59Z",
    "notificationDestination": " http://<IP адрес>:<port>",
    "reliableDataService": false,
    "status": "ACTIVE",
    "niddDownlinkDataTransfers": []
}

Удаление конфигурации на SCEF


Ну и последним – удалим созданную нами конфигурацию. Для этого используем ту же строку адреса, что и в получении текущей конфигурации, но сменим ее на DELETE:


В ответ нам поступит:

{
    "externalId": " <ID устройства>",
    "duration": "2020-12-31T23:59:59Z",
    " notificationDestination": " http://<IP адрес>:<port>",
    "reliableDataService": false,
    "status": "TERMINATED"
}

Где в строке “status” увидим, что созданная нами конфигурация удалена.

Заключение


На тему использования SCEF можно написать не одну диссертацию, тема обширна и скоро станет крайне актуальной для многих М2М устройств во всех сферах и в первую очередь для интернета вещей. Главное, что я хотел до вас донести – то, как начать работать с NIDD и SCEF «из коробки», чтобы дальше вы могли разобраться самостоятельно. Но также я всегда рад вам помочь: support@simcom.com (с пометкой for RUS Team), в письме нужно обязательно указать свои контактные данные и пару слов о вашем проекте.

В следующих статьях мы внимательно разберем другие аспекты работы с сотовыми модулями, а вы напишите в комментариях какая тема будет для вас интересна.

Хочу сказать отдельное спасибо старшему эксперту конвергентных решений и мультимедийных сервисов – Новикову Сергею (sanov) из компании МТС за неоценимую помощь в подготовке статьи.

Используемые источники


NB-IoT: как он работает? Часть 3: SCEF – единое окно доступа к услугам оператора
ETSI TS 129 122