RU

Создание обработчика

Для создания нового обработчика перейдите на вкладку Обработчики. Добавьте обработчик, нажав на плюсик.

Заполните следующие поля:

  • имя — наименование обработчика;

  • описание — подробная характеристика обработчика, заполняется при необходимости;

  • параметры по умолчанию — поведение обработчика при получении пакета данных, в котором нет нужных входных аргументов:

    • брать последнее присланное значение — в качестве значений недостающих в пакете параметров будет подставлено последнее полученное значение по этим параметрам.
      Например, в обработчике вы рассчитываете эффективную температуру на базе двух входных значений: температура и влажность, однако они приходят не в одном пакете, а в разных, последовательно. Тогда при получении только температуры обработчик сам возьмет последнее полученное значение влажности для расчета, и наоборот.

    • заменять на “null” — в качестве значений недостающих в пакете параметров будет подставлен “null”. Например, в обработчике вы рассчитываете среднее значение скорости на базе последних десяти значений. Однако скорость вы получаете не в каждом пакете. Если вы выберете режим “брать последнее присланное значение”, то при получении пакета без скорости обработчик возьмет последнее значение скорости и проведет для него расчет. Вы получите некорректную выходную величину. Если же вы выберете режим “заменять на “null”, то такую ситуацию вы можете обработать и не проводить расчет:

      if (speed === null) {
        return {};
      }

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

  1. Сохранить: Сохранить изменения обработчика. Если ранее обработчик был запущен на объектах, он продолжит работать уже в обновленной версии
  2. Тестировать: Открыть окно тестирования, в котором можно ввести входные параметры и проверить получившиеся выходные значения
  3. Download .js: Экспортировать обработчик в файл формата JSON
  4. В данной части комментария указывается дополнительное описание обработчика
  5. В данной части комментария указывается логин автора обработчика
  6. В данной части комментария указываются входные параметры в следующем формате
  * @param {<тип_данных>} <имя> <описание>

Пример:

 * @param {string} rawData input data in base64 format
  1. В круглых скобках указываются имена входных параметров в следующем формате
function process(параметр_1, параметр_2, ..., параметр_n)

Пример:

function process(rawData)
  1. Код обработчика, работающий с входными параметрами по заданному алгоритму

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

return {параметр_1, параметр_2, ..., параметр_n};

Пример:

return { time, hypotenuse };
💡

Подсказка: Входных и выходных параметров может быть несколько.

Встроенные библиотеки и модули

Обработчики поддерживают стандарт ECMAScript вплоть до версии языка ES2019. Также в них имеются все стандартные объекты JavaScript:

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

Во время проектирования процесса обработки данных и создания обработчика у вас может возникнуть потребность в подключении и использовании вспомогательных функций. Помимо стандартных библиотек в архитектурный слой обработки данных добавлен объект ric, включающий в себя дополнительные методы:

  • генерация событий;
  • декодирование Base64;
  • организация локального хранилища.

Генерация событий

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

/**
 * @param {number} a sample param 1
 * @param {number} b sample param 2
 */
 
function process(a, b) {
  const sum = a + b;
  if (sum > 25) {
    ric.events.gen("model-event-01", { sum });
  }
  return { sum };
}

Декодирование Base64

Следующий код обработчика позволяет получить параметры { lat, lon } из восьмибайтного буфера. ric.base64.decode принимает строку Base64 и возвращает JavaScript DataView (opens in a new tab).

/**
 * Parse { lat, lon } params from binary
 *
 * ```
 * +----------+----------+
 * | lat      | lon      |
 * +----------+----------+
 * | 32bit be | 32bit be |
 * | ieee 754 | ieee 754 |
 * +----------+----------+
 * ```
 *
 * @param {string} payload base64 encoded bytes
 */
function process(payload) {
  const buf = ric.base64.decode(payload);
 
  return {
    lat: buf.getFloat32(0),
    lon: buf.getFloat32(4),
  };
}
 
// test Ql8Z6EIWn/M=

Локальное хранилище

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

/**
 * Calc average of last 10 a's
 * @param {number} a sample param
 */
 
function process(a = 0) {
  /* init local store with default values (if empty)
     and reduce it with fresh values */
  const { counter, last10 } = ric.localStore.forObject
    .initWith({
      counter: 0,
      last10: [a],
    })
    .reduce((prev) => ({
      counter: prev.counter + 1,
      last10: [...prev.last10, a].slice(-10),
    }));
 
  /* calc sum and avg of last 10 values */
  const sum = last10.reduce((acc, val) => acc + val, 0);
  const avg = sum / last10.length;
 
  return {
    counter,
    sum,
    avg,
  };
}
💡

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

Сторонние библиотеки и модули

Помимо использования уже встроенных возможностей обработчиков, вы можете подключить сторонние библиотеки по ссылке. Сама библиотека должна быть написана на языке JavaScript и соответствовать спецификации ESM (EcmaScript modules) (opens in a new tab).

Ограничения на подключаемые библиотеки:

  • максимальный размер библиотеки — 65 Кбайт;

  • в коде должны использоваться только стандартные объекты JavaScript (opens in a new tab). Если библиотека использует какие-то расширенные API (например, Buffer из Node.js), или их встроенные модули (например, fs, path), или браузерные API (fetch, WebSocket), то она не заработает.

В случае нарушения ограничений обработчик не будет сохранен.

Для импорта из npm уже имеющихся библиотек можно воспользоваться сервисами:

Подключение Javascript модуля

В качестве примера возьмем с GitHub простой Javascript модуль (opens in a new tab), который считает сумму двух чисел

export function sum(a, b) {
  return a + b;
}
💡

Подсказка: Можно использовать не только GitHub репозиторий, но и любые другие интернет-адреса, по которым доступно содержимое необходимого для импорта модуля.

Следующий код обработчика позволяет суммировать два числа при помощи использования импортированной функции из модуля.

import { sum } from "https://raw.githubusercontent.com/rightech/ric-examples/master/handlers/lib/example.js";
 
function process(a, b) {
  const res = sum(a, b);
  return { sum: res };
}
💡

Важно: Обратите внимание, что при импорте модулей с GitHub репозитория необходимо использовать их “raw” версию, т.к. иначе сервер GitHub будет отдавать HTML страницу для просмотра, а не само содержимое файла. Для получения нужного адреса ссылки нажмите кнопку Raw в интерфейсе GitHub.

💡

Подсказка: Если вас смущает, что слово process при подключении сторонних библиотек становится бледным, добавьте слово export перед словом function.

Подключение библиотеки из npm

В качестве примера возьмем пакет gps (opens in a new tab) c сервиса Skypack (opens in a new tab).

Следующий код обработчика позволяет разбирать строку, полученную в формате NMEA, и извлекать из нее координаты.

import GPS from "https://cdn.skypack.dev/gps@0.6.1";
 
function process(nmea) {
  const gps = new GPS();
 
  let lat = 0;
  let lon = 0;
 
  gps.on("data", (parsed) => {
    lat = parsed.lat;
    lon = parsed.lon;
  });
 
  gps.update(nmea);
 
  return { lat, lon };
}
💡

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