Хабрахабр

ThingJS v1.0-alpha

Последние два года я разрабатывал собственную IoT платформу и сегодня готов показать ее альфа версию.

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

Важным замечанием будет то, что платформа должна заинтересовать (внезапно) JavaScript разработчиков, т.к. Статья будет интересна людям, которым близка тема IoT и они уже что-то делали в этой сфере. Конечно, и С/С++ разработчикам тоже будет что почитать. именно этот язык выбран как основа платформы.

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

Оглавление

— Проблема коротких рук

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

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

— Проблема Вавилонской башни

Быть фулстеком в IoT это прям… сложно. Разработка полноценной IoT экосистемы требует очень широкий технологический стек. Похвастаться таким широким спектром знаний, да еще и опытом, могут далеко не все. Нужен опыт везде. Это очевидный вывод из проблемы “коротких рук”. И тут вопрос не в умственных способностях.

Говорят эти специалисты на разных языках, используют разные паттерны, да и часто элементарные термины они понимают по-разному. Для создания действительно состоятельной экосистемы требуется труд многих достаточно узких специалистов, но с глубокими знаниями в свой области. А учитывая, что IoT базируется на устройствах с ограниченными ресурсами, эффективные коммуникации критически важны для реализации задуманного.

— Проблема Стокгольмского синдрома

Это Google, Microsoft, Yandex, Мегафон, МТС и т.д. Сегодня есть вендоры, которые развивают свои экосистемы. Это во многом закрывает выше описанные проблемы. Некоторые из них позволяют интегрировать собственные вещи в их экосистемы на их условиях. А условия интеграции вендоры очень любят менять. Но создает новую — зависимость. И уж, тем более о самореализации в этой парадигме речи не идет.

Разработка платформы была начата с осознанием этих проблем. Выше описанные проблемы, фактически, закрывают доступ к разработке IoT для индивидуалов. В основу было заложено развитие платформы через сообщество.

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

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

Это кардинально решает проблему “коротких рук”. Таким образом, одновременно, независимо, множество людей могут разрабатывать собственные компоненты платформы и переиспользовать уже имеющиеся, разработанные кем-то.

Зависимости построены так, что различные уровни платформы, разрабатываемые на разных языках, имеют заранее определенный механизм выстраивания зависимостей между собой. Также, решается проблема “Вавилонской башни”.

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

— Больше обещаний и абстракций

Вместо него есть абстракция — шина данных. Протокол общения между устройствами неопределен. Кто в шину пишет и кто получает, заранее неясно. Устройство может послать в шину событие или прослушать шину. Обмен данными асинхронный и доставка не гарантируется. И когда тоже. Без паники. В общем — ад. Так задумано.

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

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

Протокол синхронного канала определяется самим типом события. Проблема синхронной связи решается передачей через шину событий со ссылками на синхронные каналы. Таким образом, получатель будет знать, что нужно воспроизвести видеопоток с указанного адреса. К примеру, можно отправить событие с типом “do-render-video-stream” и как payload передать IP WEB-камеры.

Реализация шины возлагается на сообщество. Но как физически работает шина? Например, событие получается по http и ретранслируется по UART. Шина расширяется тем транспортом, который требует ваш проект. Для всех элементов экосистемы внешне ничего не изменится.

Более того, физическая вещь может содержать в себе несколько виртуальных вещей (приложений), которые используют ресурсы физической вещи. Для ThingJS вещью является не только физическая вещь, но и специальное приложение — виртуальная вещь.

Построить матрицу, а не иерархию взаимодействия. Такой подход позволяет унифицировать взаимодействие между условным backend (контроллер/сервер/облако и т.п.) и frontend (браузер, приложение и т.п.), а также b2b и даже f2f.

Когда пользователь заходит по адресу http://192. Простым примером может быть WEB-камера, которая в себе имеет виртуальную вещь — интерфейс пользователя. 4. 168. Камера (физическая вещь) и страница (виртуальная вещь) автоматически становятся экосистемой, где доступна унифицированная шина данных. 1 открывается WEB страница, где начинает “жить” виртуальная вещь. В этом случае: физическая вещь сообщает виртуальной вещи через шину адрес видеопотока, свое состояние и т.п., а виртуальная демонстрирует пользователю видео и отдает необходимые команды физической вещи. Через нее виртуальная вещь общается с физической.

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

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

Структура приложения ThingJS

Стек технологий

Платформа проектировалась аппаратно независимой. Аппаратной платформой выбран контроллер ESP32. Но, к сожалению, партировать на иные устройства не было времени.

Прошивка разработана на языке С. Для разработки прошивки используется рекомендованные Espressif средства. Проект использует концепцию компонентов, также продвигаемую Espressif. Сборщик cmake.

Помимо, esp-idf, используются Mongoose WEB Server, а также доработанный JavaScript интерпритатор Mongoose mJS.

Сборка приложений осуществляется посредством webpack. Для разработки приложений используется JavaScript с фреймворком VUE 2. Как основа для среды разработки использовался VUE CLI. Менеджер пакетов — npm.

Для того чтобы стандартизировать визуализацию приложений и облегчить муки UI творчества, в платформу включен пакет vuetifyjs.

Возможности среды разработки

Для JavaScript разработчиков (виртуальные вещи):

  • Рекомендованная IDE — WEBStorm;
  • Все профиты, которые дает VUE CLI и IDE;
  • Внутрисистемная отладка приложений (дебаггер mJS на контроллере);
  • В mJS реализована команда debugger, позволяющая вызывать отладчик в произвольном месте;
  • Горячая загрузка обновленных файлов на контроллер при разработке (JavaScript девелоперы уже без этой фичи не живут);
  • Runtime разработка в паре с реальным контроллером. Программируешь и, тут же, видишь результат на железе;
  • Настроенный ESLint для понимания объектов платформы.

Для С разработчиков (физические вещи):

  • Рекомендованная IDE — CLion;
  • Все профиты esp-idf и IDE;
  • Платформа разделена на компоненты в рамках концепции esp-idf;
  • Легкая интеграция с платформой собственных компонентов.

Поддерживаемые устройства

Чип популярен, ввиду своей доступности при поразительных технических характеристиках. В настоящий момент поддерживается только ESP32. На его базе создано достаточно много готовых IoT устройств, которые можно использовать под управлением ThingJS.

Сравнение с конкурентами

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

Мне только посмотреть

Хочу попробовать

Но лучше всего подойдет ESP32 core board v2. Для того чтобы попробовать платформу на реальном железе, вам понадобится любое устройство на базе ESP32 c flash 4mb и возможностью его прошивать через USB.

Более того, есть даже представительства в России. Купить такие штуки можно без проблем на Aliexpress или Ebay. Я лично покупаю в Питере.

На некоторых версиях плат есть предустановленный светодиод, подключенный к GPIO2. Для того чтобы проверить работу тестового приложения “Blink”, потребуется подключить светодиод. Blink должен работать без лишних движений. Если у вас такая плата, то можно ничего не делать. В этом нет ничего сложного. Если у вас только один диод (питание), то придется подключить индикаторный диод самому.

Вам понадобится любой индикационный светодиод и сопротивление от 1 до 5КОм.

Взять его можно тут. Осталось дело за малым — развернуть пользовательский пакет на устройстве. Инструкция по развертыванию находится там же.

Виртуальное устройство запускается из физического при обращении к нему через браузер. Blink это простейшая экосистема состоящая из одного виртуального устройства, реализующего интерфейс пользователя, и одного физического.

При установке приложения на физическом устройстве начинает мигать светодиод (заранее к нему подключенный) с частотой 1Гц. Сценарий прост. Видео можно посмотреть в разделе “Мне только посмотреть”. Пользователь может включать или выключать мигание диода из интерфейса.

Для того чтобы собрать blink и с ним “поиграться”, вам понадобится только этот репозиторий. Исходники лежат в репозитории src/applications/blink. Убедитесь, что git, npm и nodejs у вас уже установлены.

git clone --branch alpha https://github.com/rpiontik/ThingJS-front
cd ThingJS-front
npm install
npm run build

Если все прошло гладко, то в результате вы получите примерно следующее:

Вы собрали свое первое приложение для ThingJS. Поздравляю! Найти его можно в папке dist/apps/blink и сразу же попробовать поставить на устройство, руководствуясь видео из раздела "Мне только посмотреть".

Я заострю внимание на нескольких файлах. Со всеми деталями приложения вы можете познакомиться самостоятельно.

, "components": {...}, "scripts": {...}, "requires" : {...}
}

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

"components": { "blink-app": { "source": "blink.js", "intent_filter": [ { "action": "thingjs.intent.action.MAIN", "category": "thingjs.intent.category.LAUNCH" } ] } }

Поле “source” указывает на точку монтирования компонента (см. Блок описывает всю компонентную базу приложения. Таким образом, каждый компонент будет оформлен в отдельный бандл. blink.js) и является точкой входа сборки для webpack (entry). Загрузка этого бандла будет выполняться по мере необходимости (lazy load).

Если вам случалось программировать для Android, вы найдете нечто знакомое для себя. Важной структурой является “intent_filter”. В системе возникают интерфейсные и сервисные события на которые подписывается компонент. И не ошибетесь. Если возникает событие, удовлетворяющее условиям фильтрации, то компонент будет загружен и управление будет передано точке монтирования.

Когда лаунчер будет запускать приложение, именно этот компонент будет представлен. В данном случае, компонент “blink-app” подписан на событие запуска основного интерфейсного компонента приложения.

Если модифицировать манифест, изменив строчку

LAUNCH >> thingjs.intent.category. thingjs.intent.category. PREFERENCE

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

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

"scripts": { "entry": "blink", "subscriptions" : ["$-script-restart", "blink"], "modules": { "blink": { "hot_reload": true, "source": "scripts/blink.js", "optimize": false } }
}

Этот блок аналогичен по функции блоку “components”, но описывает компонентную базу приложения на стороне контроллера.

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

Сейчас в нем указаны два события: За подписки отвечает поле “subscriptions”.

  • $-script-restart — возникает в случае запуска или перезапуска системы;
  • blink — кастомное событие, которое релевантно для экосистемы blink.

Отмечу два поля: В блоке “modules” следует описание состава скриптов.

  • hot_reload — если это поле установлено в true, то при изменении файла в режиме разработки он автоматически будет загружаться на контроллер (hot reload);
  • optimize — если true, то при сборке проекта скрипт будет оптимизироваться и аглифицироваться.

"requires" : { "interfaces" : { "blink" : { "type" : "bit_port", "required" : true, "default" : 2, "description" : { "ru" : "LED индикатор", "en" : "LED indicator" } } }
}

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

В данном случае, чтобы приложение могло функционировать, ему требуется предоставить интерфейс с типом “bit_port”. В этом блоке указываются зависимости. В скрипт он будет спроецирован с именем “blink”. Этот интерфейс является обязательным требованием (required = true) и по умолчанию, указывается GPIO2 (default = 2).

В этом профиле перечисляются доступные интерфейсы и доступные для них аппаратные ресурсы (в частности, пины и их комбинации). При установке приложения учитывается профиль оборудования, на которое будут разворачиваться скрипты. Если оборудование может удовлетворить требованиям приложения, пользователю отображается схема распределения ресурсов, где первично ресурсы распределены автоматически с учетом рекомендаций из манифеста. Проверяется совместимость требований и оборудования. из того самого поля “default”. Т.е.

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

import App from './Blink.vue';
import Langs from './langs'; $includeLang(Langs);
$exportComponent('blink-app', App);

manifest.js/components) В нем выполняется регистрация VUE компонента ‘blink-app’ через метод абстракции $exportComponent, а также регистрируется языковой пакет. Файл является точкой монтирования компонента, анонсированного в манифесте (см.

Почему не регистрировать сразу VUE компонент, который указывать в source? Возможно, вы спросите — зачем такие сложности? Эти компоненты могут запрашиваться сторонними приложениями (runtime зависимости). Дело в том, что манифест описывает публичные компоненты. Т.е., подготовить окружение компонента. Точка монтирования, в свою очередь, может зарегистрировать сопутствующие компоненты (для внутреннего пользования), а также сервисы.

export default { name: 'Blink', watch: { blink_state (state) { // Send event to script this.$bus.$emit($consts.EVENTS.UBUS_MESSAGE, 'blink', state); } }, data () { return { blink_state: true }; }
};

При изменении свойства “blink_state” отправляется сообщение в шину ($bus) с текущим значением. Код говорит сам за себя. Это все, что нужно сделать, чтобы скрипт на стороне контроллера получил нужную команду.

let active = true;
let state = true; // Set port direction
$res.blink.direction($res.blink.DIR_MODE_DEF_OUTPUT); // Run background process
setInterval(function () { if (active) { // $res - is container with required resources $res.blink.set(state); // Do invert state = !state; }
}, 1000); // Event listener
// $bus - system bus interface
$bus.on(function (event, content, data) { if (event === 'blink') { active = !!JSON.parse(content); }
}, null);

За исключением того, что в данном диалекте JavaScript его нет. В целом, код очень похож на классическое использование таймера в JavaScript. Знакомьтесь, это mJS. Он реализован в платформе. Более подробно о нем можно узнать на официальной странице проекта.

Завезены таймеры, а также такая полезная команда как “debugger”. Для нужд платформы диалект доработан. Подробнее об этом отдельно в разделе “Среда разработки”. Ну, и сам отладчик.

Они именуются с символа “$”. Обратите внимание на глобальные объекты платформы.

  • $res — содержит ресурсы, которые выделены скрипту;
  • $bus — интерфейс шины.

приложение запросило интерфейс с типом “bit_port” (см. Т.к. Интерфейс реализует всего три функции: profile.json/requires) и именем “blink”, ему он был выдан как $res.blink.

  • set(value) — установить уровень GPIO
  • get() — получить текущий уровень GPIO
  • direction(value) — установить режим GPIO

Для функции direction описаны доступные константы через тот же интерфейс $res.blink.: DIR_MODE_DISABLE; DIR_MODE_DEF_INPUT; DIR_MODE_DEF_OUTPUT; DIR_MODE_INPUT_OUTPUT_OD; DIR_MODE_INPUT_OUTPUT.

При этом в обработчик будут приходить все события, на которые скрипт подписан. Подписка на события шины осуществляется через метод $bus.on. Обработчик принимает три параметра:

  • event — идентификатор события. В этом случае возможны всего два: “$-script-restart” и “blink”. Из которых обрабатывается всего одно — blink. Подписка на второе нужна лишь для того, чтобы скрипт запускался сразу при старте системы.
  • content — с событием могут приходить данные. Их размер ограничен 126 байтами с учетом длины идентификатора события.
  • data — данные, которые передаются при подписке на событие как второй параметр. И в данном случае, равны null.

Ниже вы найдете описание, как создать собственный интерфейс. Интерфейсы расширяемы.

Реализация интерфейса

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

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

Для того чтобы начать, потребуется развернуть проект ThingJS-template alpha релиз. Рассмотрим реализацию интерфейса “bit_port”, который используется в примере “Blink”. Документация по развертыванию находится в самом проекте.

git clone --branch alpha https://github.com/rpiontik/ThingJS-template

В проект входят компоненты:

  • ThingJS-boards — содержит в себе конфигурации устройств. Пока только ESP32_CORE_BOARD V2 и совместимые;
  • ThingJS-extern — библиотеки сторонних проектов, которые использует ThingJS;
  • ThingJS-core — ядро платформы;
  • ThingJS-front — среда разработки приложений;
  • ThingJS-stdi — стандартные интерфейсы.

Его структура следующая: Нас интересует проект ThingJS-stdi.

Именно в нем содержится все, что требует отдельного пояснения. По сути, нас интересует только один файл — implementation/tgsi_bit_port.c.

void thingjsBitPortRegister(void) { static int thingjs_bit_port_cases[] = DEF_CASES( DEF_CASE(GPIO0), DEF_CASE(GPIO2), DEF_CASE(GPIO3), DEF_CASE(GPIO4), DEF_CASE(GPIO5), DEF_CASE(GPIO12), DEF_CASE(GPIO13), DEF_CASE(GPIO14), DEF_CASE(GPIO15), DEF_CASE(GPIO16), DEF_CASE(GPIO17), DEF_CASE(GPIO18), DEF_CASE(GPIO19), DEF_CASE(GPIO21), DEF_CASE(GPIO22), DEF_CASE(GPIO23), DEF_CASE(GPIO25), DEF_CASE(GPIO26), DEF_CASE(GPIO27), DEF_CASE(GPIO32), DEF_CASE(GPIO33) ); static const struct st_thingjs_interface_manifest interface = { .type = "bit_port", .constructor = thingjsBitPortConstructor, .cases = thingjs_bit_port_cases }; thingjsRegisterInterface(&interface);
}

Для этого она вызывает функцию thingjsRegisterInterface, которой передает структуру с описанием интерфейса. Функция thingjsBitPortRegister регистрирует компонент в ядре ThingJS.

  • type — идентификатор интерфейса. Именно он указывается как тип в файле manifest.json приложения;
  • constructor — ссылка на конструктор интерфейса. Функция вызывается каждый раз, когда нужно создать новый экземпляр интерфейса;
  • cases — массив, описывающий возможные аппаратные ресурсы, которые может использовать интерфейс для своей работы. В данном случае, это одиночные GPIO. Но могут быть отдельно описаны их комбинации или зависимости.

Конструктор интерфейса монтирует интерфейс в машину mJS.

mjs_val_t thingjsBitPortConstructor(struct mjs *mjs, cJSON *params) { //Validate preset params //The params must have pin number if (!cJSON_IsNumber(params)) return MJS_UNDEFINED; //Get pin number gpio_num_t gpio = params->valueint; //Create mjs object mjs_val_t interface = mjs_mk_object(mjs); /* Configure the IOMUX register for pad BLINK_GPIO (some pads are muxed to GPIO on reset already, but some default to other functions and need to be switched to GPIO. Consult the Technical Reference for a list of pads and their default functions.) */ gpio_pad_select_gpio(gpio); //Add protected property to interface mjs_set(mjs, interface, "gpio", ~0, mjs_mk_number(mjs, gpio)); //Set protected flag mjs_set_protected(mjs, interface, "gpio", ~0, true); //Bind functions mjs_set(mjs, interface, "set", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortSet)); mjs_set(mjs, interface, "get", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortGet)); mjs_set(mjs, interface, "direction", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortDirection)); //Consts mjs_set(mjs, interface, "DIR_MODE_DISABLE", ~0, mjs_mk_number(mjs, GPIO_MODE_DISABLE)); mjs_set(mjs, interface, "DIR_MODE_DEF_INPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_DEF_INPUT)); mjs_set(mjs, interface, "DIR_MODE_DEF_OUTPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_DEF_OUTPUT)); mjs_set(mjs, interface, "DIR_MODE_INPUT_OUTPUT_OD", ~0, mjs_mk_number(mjs, GPIO_MODE_INPUT_OUTPUT_OD)); mjs_set(mjs, interface, "DIR_MODE_INPUT_OUTPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_INPUT_OUTPUT)); //Return mJS interface object return interface;
}

Как параметры передаются:

  • mjs — глобальный контекст выполнения;
  • params — параметры инициализации интерфейса. В данном случае это номер GPIO.

Создается объект mJS “interface”, куда монтируются методы и свойства интерфейса:

  • gpio — readonly свойство, в котором хранится номер используемого GPIO;
  • set — метод установки уровня сигнала;
  • get — метод получения текущего уровня сигнала;
  • direction — установка режима GPIO;

Также, монтируются константы, которыми смогут оперировать скрипты (DIR_MODE_DISABLE, DIR_MODE_DEF_INPUT и т.д.).

Пример использования можно посмотреть в разделе Blink (scripts/blink.js). После создания интерфейса, он монтируется под определенным идентификатором (в примере Blink это “blink”) в глобальный объект $res.

Это позволит собирать прошивку как лего. Вы можете оформлять интерфейсы в отдельные компоненты или пакеты.

Разработка приложений

Это жесткий форк, т.ч. Среда разработки приложений основывается на VUE CLI, который был доработан для соответствия потребностям платформы ThingJS. новых фич из VUE CLI стоит ждать в том случае, если они прям сильно облегчают жизнь.

Убедитесь, что git, npm и nodejs у вас уже установлены. Для развертывания среды необходимо клонировать проект ThingJS-front alpha-релиз.

git clone --branch alpha https://github.com/rpiontik/ThingJS-front
cd ThingJS-front
npm install

При разработке рекомендую использовать IDE WEBStorm.

Я отражу значимые отличия: Состав и структура проекта наследует VUE CLI.

  1. Переработаны скрипты сборки в папке build.
  2. В конфиг dev среды (config/dev.env.js) добавлена переменная окружения “HW_DEVICE_URL”. В ней необходимо указывать ссылку на физическое устройство с которым вы будете работать.
  3. Появилась системная папка src/applications. В ней содержатся приложения, которые будут собираться автоматически. В частности, в ней находятся два приложения: ante (лаунчер) и blink (приложение).
  4. Все, что выше папки src/applications считается платформенными модулями и ресурсами. Вы, конечно, можете вносить изменения в них, но в этом случае, они появятся в контроллере только после его перепрошивки. Т.ч. если специально вы себе цели не ставили, лучше их не трогать.

Хотя полноценно вы не сможете проводить разработку без физической “железки”, разрабатывать интерфейс это не мешает. Для пробы, можно тут же запустить dev-сервер. И так, запускам dev-сервер:

npm run dev

Результат должен быть примерно таким:

0. Открыв браузер и введя в адресную строку http://0. 0:8080 вы увидите платформу в режиме разработки: 0.

За исключением того, что есть глобальные объекты платформы, о которых нужно знать: Сам процесс разработки интерфейса мало чем отличается от классической разработки фронта на VUE.

  • $const — содержит в себе платформенные константы, а также языковые пакеты;
  • $bus — Шина данных;
  • $store — глобальное хранилище (VUEX).
    Из примеров вы сможете понять как их использовать.

Указываете языковую константу, она интерпретируется в текст в зависимости от языка интерфейса. Мультиязычность реализована простейшим образом — через фильтр “lang”.

v-bind:label="'BLINK_SATE' | lang"

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

Для этого в браузере наберите http://[IP контроллера]. После прошивки контроллера и подключения в сеть, нужно убедиться, что контроллер доступен по IP с вашего компьютера. Должен открыться WEB-интерфейс.

Теперь требуется указать адрес контроллера в файле config/dev.env.js

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', HW_DEVICE_URL: '"http://[IP контроллера]"' //HW_DEVICE_URL: '"http://192.168.8.105"', //HW_DEVICE_URL: '"http://192.168.4.1"',
})

В будущем, после изменения файлов сборки, конфигурации, а также манифестов приложений, всегда перезапускайте dev-сервер. Если dev-сервер был запущен, остановите его и вновь запустите.

Это не фича, а баг альфы. Хотя при работе в dev-среде отображаются все приложения, которые есть в папке src/application как установленные, полнофункционально будут работать только те, которые действительно установлены на контроллер. Но пока, нужно поставить в ручном режиме приложение на контроллер, чтобы среда его “зацепила” и синхронизировала с тем, что есть в dev. В будущем синхронизация железки и dev-среды будет происходить автоматически.

Собираем приложение в прод режиме:

npm run prod

Не через dev-сервер. Устанавливаем собранные приложения на контроллер напрямую.

Любые ваши изменения файлов будут автоматически запускать пересборку приложений и картинка на экране будет меняться (hot reload). Вот теперь можно приступить к разработке. К примеру, можно добавить в скрипт приложения blink команду debugger и посмотреть результат. Это же правило распространяется на срипты контроллера.

// Event listener
// $bus - system bus interface
$bus.on(function (event, content, data) { if (event === 'blink') { debugger; active = !!JSON.parse(content); }
}, null);

Теперь при изменении состояния чекбокса приложения Blink, среда разработки выкинет такое сообщение:

Отобразится строка на которой произошла остановка. Кликнув по ссылке “Start debugger”, вы попадете в отладчик.

Сам процесс отладки мало чем отличается от прочих отладчиков.

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

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

Разработка прошивки

Переплюнуть родную документацию на этот счет я не смогу. Разработка прошивки основывается на концепции предложенной Espressif.

В нем содержится информация по развертыванию. Для быстрого старта подготовлен репозиторий. Пример использования смотрите в разделе “Реализация интерфейса”.

Сборка очень простая и буквально через 1-2 часа вы будете уже собирать прошивки без проблем.

Дальше, если платформа заинтересует сообщество, планируется:

  • Развитие среды отладки;
  • Стандартизация именований интерфейсов, событий, компонентов;
  • Подробная документация на платформу;
  • Облачный хостинг для виртуальных вещей;
  • Runtime репозитории;
  • Партирование на различные готовые устройства.

Она уже очень большая по размаху и амбициям. Также, я ищу людей, которые хотели бы развивать платформу со мной. Я предполагаю равноправное сотрудничество, целью которого станет развитие платформы до полноценной на принципах OpenSource.

Для вступления в проект необходимо сделать ценные pull-реквесты в интересующие вас компоненты платформы.

Ресурсы проекта ThingJS:

Репозитории проекта ThingJS:

Используемые проекты:

Тут будут появляться ответы на вопросы в комментариях.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть