Структура конфигурации¶
Конфигурация – это JSON-файл, который задает поведение системы на клиенте и сервере. На сервере – конфигурация это по большей части – набор классов узлов. Узлы хранятся и выполняются по мере обращения к ним со стороны клиентов и внешней системы. А для мобильного клиента в конфигурации задаются многие другие свойства.
Какие разделы есть в конфигурации
Общие свойства (Название конфигурации, поставщик, версия и т.д.)
Разделы. То, на каких вкладках в интерфейсе располагаются узлы и процессы. Подробнее в разделе Мобильный клиент
Классы. Структура классов данных – и серверных и клиентских. Подробнее в разделе Классы
Общие события. События, возникающие в системе вне классов узлов, т.е. в приложении в целом. Подробнее в подразделе «Общие события мобильного клиента»
Разделы с python-обработчиками для классов и общих событий. Это python-файлы, преобразованные в base64-формат, хранящиеся в структуре конфигурации. Доставляются на целевое устройство вместе с обновлением конфигурации и преобразуются в исполняемые временные файлы.
Датасеты. Хранение и доставка справочников и ссылок внешней системы на устройство. Подробнее в разделе Датасеты
Серверы – раздел для регистрации псевдонимов серверов, использующихся в функциях API
Описание формата файла¶
Некоторые из полей этого раздела формируются автоматически конструктором, но в случае формирования файла вне контрактора (например LLM) все поля необходимо будет заполнять согласно принципам, описанным ниже
Общие свойства конфигурации¶
«name» – имя конфигурации
«uid» – ИД установки на сервере, через который организуется доступ к объектам конфигурации для API и хранение
«url» – полный адрес хостинга, с которого клиенты будут скачивать конфигурацию(конфигурация изначально может быть попасть на клиент с файла, но для обновления он будет обращаться по этому адресу)
«content_uid» – уникальный ID конфигурации независимо от ИД уставновки. Одна и та же конфигурация может быть развернута под разными uid, но content_uid останется тем же
«vendor» имя поставщика конфигурации
«version» – номер версии.
«NodaLogicFormat» – версия формата. Анализируется приложением. Если приложение не поддерживает этот формат, будет предложено обновить приложение
«NodaLogicType»: «ANDROID_SERVER» – константа
Обработчики¶
«nodes_handlers» и «nodes_server_handlers» – base64 закодированные файлы обработчиков. Они должны быть оформлены по определенному стандарту – верхняя часть содержим импорты и константы, которые автоматически генерируются системой. Далее идут классы и пользовательский код. В current_module_name прописывается url инстанса, в current_configuration_url – путь к API инстанса. Т.е. поля uid и url
Для андроид это:
from nodesclient import RefreshTab,SetTitle,CloseNode,RunGPS,StopGPS,UpdateView,Dialog,ScanBarcode,GetLocation,AddTimer,StopTimer,ShowProgressButton,HideProgressButton,ShowProgressGlobal,HideProgressGlobal,Controls,SetCover,getBase64FromImageFile,convertImageFilesToBase64Array,saveBase64ToFile,convertBase64ArrayToFilePaths,UpdateMediaGallery
from android import *
from nodes import NewNode, DeleteNode, GetAllNodes, GetNode, GetAllNodesStr, GetRemoteClass, CreateDataSet, GetDataSet, DeleteDataSet,to_uid, from_uid
from com.dv.noda import DataSet
from com.dv.noda import DataSets
from com.dv.noda import SimpleUtilites as su
from datasets import GetDataSetData
# Константы конфигурации
current_module_name="296f962e-bd0d-4b32-8ac8-3bc9a1162a56"
current_configuration_url="http://nmaker.pw/api/config/296f962e-bd0d-4b32-8ac8-3bc9a1162a56"
_data_dir = su.get_data_dir(current_module_name)
_downloads_dir = su.get_downloads_dir(current_module_name)
from nodes import Node
Для server это:
from nodes import Node
Классы¶
«classes» – массив классов
Каждый класс должен присутствовать и в массиве classes и также быть в обработчике, в зависимости от того где он будет выполняться. Либо в «nodes_handlers» либо в «nodes_server_handlers»
Класс имеет ключи:
«name» – имя, оно же идентифкатор класса. Должно быть python-совместимым (так как на этот класс в python также существует класс)
«section_code» и «section» – код раздела и название раздела (из раздела конфигурации sections) к которому отностится класс
«has_storage» – автосохранение данных при вводе в поля ввода
«display_name» – отображаемое имя, елси не используется «обложка»
«cover_image» – обложка в формате разметки, таком же как для экранов и люых мест где используется разметка в Андроид- клиенте
«hidden» – класс (если это класс-процесс) будет скрыт для отображения в интерфейсе)
«class_type» – доступно либо «custom_process» – узел-процесс, существующий в единственно экземпляре, создается вместе с загрузкой конфигурации либо «data_node» – узел данных, т.е. объект данных создаваемый или загружаемый в систему
«methods» – массив методов класса. Методы должны быть описаны и в массиве и в обработчиках.
Ключи метода:
«name» и тоже самое в «code» (для совместимости)– имя метода
«source»: «internal»
«engine» : либо «android_python» либо «engine»: «server_python» в зависимости от того, где планируется выполнять метод
«events» – массив событий, которые возникают в системе – открытие формы, действия пользователя
Ключи события:
«event» – может быть «onShow» (при открытии формы узла), «onResume» ,»onInput» – любое событие ввода от пользователя или внешнее событие
«listener» – фильтр по «listener». События ввода как правило содержат дополнительное поле «listener», уточняющее событие. Например, id нажатой кнопки. Если не использовать «listener» то все события будут попадать на этот обработчик
«actions» – массив действий, который надо выполнить на событие. На одно и то же событие можно повесить несколько действий, но обычно оно одно.
Ключи действия:
«action» -«run»(синхронное выполнение), «runasync» – асинхронное выполнение, «runprogress» – синхронное с прогрессбаром.
«source» : «internal»
«method» : имя метода из массива «methods»
«postExecuteMethod» – имя метода, который может быть выполнен после окончания выполнения основного метода. Актуально для асинхронного выполнения и выполнение с прогрессбаром.
Помимо прописывания в classes класс узла также необходимо разместить в обработчиках, используя то же имя и те же имена методов и соблюдая определенный формат описания – класс родитель, метод __init__.
Для Андроид пример:
class MyClass(Node):
def __init__(self, modules, jNode, modulename, uid, _data):
super().__init__(modules, jNode, modulename, uid, _data)
"""Class MyClass"""
def Open(self, input_data=None):
self.Show(
[
[{"type":"Input","id":"input1","caption":"input 1","value":"@input1"}],
[{"type":"Button","id":"button1","caption":"Get result"}]
]
)
return True,{}
def Input(self, input_data=None):
toast(self._data["input1"])
return True,{}
Для сервера:
class MyClass(Node):
def __init__(self, node_id=None, config_uid=None):
super().__init__(node_id, config_uid)
Также при оформлении методов класса нужно придерживаться единого формата , описанного в разделах Классы и Общие обработчики. Это параметры метода и структура возвращаемого кортежа. Для методов класса:
def Input(self, input_data=None):
return True,{}
Для общих обработчиков:
def onStartConfiguration(input_data):
return True,{}
Секция Разделы¶
«sections» – массив разделов
«name» – отображаемое имя раздела
«code» – ИД раздела
«commands» – список команд в виде списка через запятую <Заголовок команды>|<ид команды>. При нажатии на кнопку генерируется общее событие onStartMenuCommand в котором в качестве параметра передается ИД команды
Псевдонимы серверов¶
Если на клиенте используется такая конструкция как RemoteClass (по сути обертка вокруг API сервера) то надо завести хотябы один сервер с «is_default»: true. Если еще есть сервера то они также используются тут. В таком случае в функциях используются их псевдонимы. В случае одного сервера, псевдоним можно не использовать.
«servers» – массив псевдонимов серверов
Ключи объекта сервера:
«alias» – псевдоним сервера, который используется в фунциях работы с удаленными серверами
«url» – адрес сервера
«is_default» – признак сервера по умолчанию
Раздел «Датасеты»¶
«datasets» – массив объектов типа «Датасет»
«name» – имя датасета, по которому к нему обращаться в прикладном решении
- «hash_indexes» – список ключей записей для hash-индексов в виде массива. Пример: [
«barcode», «article»
]
- «text_indexes» – список полей полнотекстового поиска в виде массива. Пример: [
«name»
]
«view_template» – шаблон отображения записи датасеты в поле ввода формы. Пример: «{name}, {article}»
** «api_url» – прямой url доступа к датасету. Откуда он будет грузится. Обязательно поле. Принцип формирования видно на примере.
Пример конфигурации целиком¶
{
"name": "New configuration",
"server_name": "",
"uid": "296f962e-bd0d-4b32-8ac8-3bc9a1162a56",
"url": "http://nmaker.pw/api/config/296f962e-bd0d-4b32-8ac8-3bc9a1162a56",
"content_uid": "1dd8f18c-fd58-4c12-b610-0595fe573429",
"vendor": "Dmitry Vorontsov",
"nodes_handlers": "base64 encoded python file",
"nodes_handlers_meta": null,
"nodes_server_handlers": "base64 encoded python file",
"nodes_server_handlers_meta": null,
"version": "00.00.01",
"NodaLogicFormat": "1.1",
"NodaLogicType": "ANDROID_SERVER",
"last_modified": "2025-12-02T13:39:08.917962+03:00",
"provider": "Dmitry Vorontsov",
"classes": [
{
"name": "MyClass",
"section": "Documentation samples",
"section_code": "Documentation",
"has_storage": true,
"display_name": "MyClass",
"cover_image": "[[\"MyClass example\"]]",
"class_type": "custom_process",
"hidden": false,
"methods": [
{
"name": "Open",
"source": "internal",
"engine": "android_python",
"code": "Open"
},
{
"name": "Input",
"source": "internal",
"engine": "android_python",
"code": "Input"
}
],
"events": [
{
"event": "onShow",
"listener": "",
"actions": [
{
"action": "run",
"source": "internal",
"server": "",
"method": "Open",
"postExecuteMethod": ""
}
]
},
{
"event": "onInput",
"listener": "",
"actions": [
{
"action": "run",
"source": "internal",
"server": "",
"method": "Input",
"postExecuteMethod": ""
}
]
}
]
}
],
"datasets": [
{
"name": "goods",
"hash_indexes": [
"barcode",
"article"
],
"text_indexes": [
"name"
],
"view_template": "{name}, {article}",
"autoload": false,
"created_at": "2025-12-01T12:01:01.072524",
"updated_at": "2025-12-01T12:01:01.072554",
"api_url": "http://nmaker.pw/api/config/296f962e-bd0d-4b32-8ac8-3bc9a1162a56/dataset/goods/items",
"item_count": 0
}
],
"sections": [
{
"name": "Documentation samples",
"code": "Documentation",
"commands": ""
}
],
"servers": [
{
"alias": "main",
"url": "https://nmaker.pw",
"is_default": true
}
]
}