Configuration Structure¶
A configuration is a JSON file that defines the behavior of the system on the client and the server. On the server, a configuration is mostly a set of node classes. Nodes are stored and executed as they are accessed by clients and external systems. For the mobile client, many other properties are defined in the configuration.
What sections exist in the configuration
General properties (configuration name, vendor, version, etc.)
Sections. The tabs in the interface where nodes and processes are placed. More details in the Mobile Client section
Classes. The structure of data classes—both server and client. More details in the Classes section
Global events. Events that occur in the system outside of node classes, i.e. in the application as a whole. More details in the “Global mobile client events” subsection
Sections with python handlers for classes and global events. These are python files converted to base64 format, stored inside the configuration structure. They are delivered to the target device along with configuration updates and converted into executable temporary files.
Datasets. Storage and delivery of reference data and external system references to the device. More details in the Datasets section
Servers – a section for registering server aliases used in API functions
File format description¶
Some of the fields in this section are generated automatically by the configurator, but if the file is formed outside of the configurator (for example by an LLM), all fields must be filled according to the principles described below.
General configuration properties¶
“name” – the configuration name
“uid” – the installation ID on the server, through which access to configuration objects for API and storage is organized
“url” – the full hosting URL from which clients will download the configuration (the configuration may initially get onto the client from a file, but for updates it will use this address)
“content_uid” – a unique configuration ID independent of the installation ID. The same configuration can be deployed under different uids, but content_uid will remain the same.
“vendor” – the configuration vendor name
“version” – version number.
“NodaLogicFormat” – format version. It is checked by the application. If the application does not support this format, it will prompt the user to update the application.
“NodaLogicType”: “ANDROID_SERVER” – constant
Handlers¶
“nodes_handlers” and “nodes_server_handlers” – base64 encoded handler files. They must follow a specific standard: the upper part contains imports and constants automatically generated by the system. Then come the classes and user code. In current_module_name the instance URL is set, and in current_configuration_url—the path to the instance API. That is, the uid and url fields.
For Android this is:
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
# Configuration constants
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
For the server this is:
from nodes import Node
Classes¶
“classes” – an array of classes
Each class must be present in the classes array and also in the handler, depending on where it will be executed—either in “nodes_handlers” or in “nodes_server_handlers”.
A class has the following keys:
“name” – the name, which is also the class identifier. It must be python-compatible (since there is a corresponding python class for this class)
“section_code” and “section” – the section code and section name (from the sections configuration section) to which the class belongs
“has_storage” – autosave of data when entering values in input fields
“display_name” – display name if a “cover” is not used
“cover_image” – a cover in the same markup format as for screens and any places where markup is used in the Android client
“hidden” – the class (if it is a process class) will be hidden in the interface
“class_type” – can be either “custom_process” – a process node existing in a single instance, created when the configuration is loaded, or “data_node” – a data node, i.e. a data object created or loaded into the system
“methods” – an array of class methods. Methods must be described both in this array and in the handlers.
Method keys:
“name” and the same in “code” (for compatibility) – method name
“source”: “internal”
“engine” : either “android_python” or “engine”: “server_python” depending on where the method is intended to be executed
“events” – an array of events that occur in the system—form opening, user actions
Event keys:
“event” – can be “onShow” (when opening a node form), “onResume”, “onInput” – any user input event or external event
“listener” – a filter by “listener”. Input events usually contain an additional “listener” field clarifying the event. For example the id of the pressed button. If you do not use “listener”, all events will go to this handler.
“actions” – an array of actions to be performed on the event. Several actions can be attached to the same event, but usually there is just one.
Action keys:
“action” – “run” (synchronous execution), “runasync” – asynchronous execution, “runprogress” – synchronous with a progress bar.
“source” : “internal”
“method” : the method name from the “methods” array
“postExecuteMethod” – the name of a method that can be executed after the main method has finished. Relevant for asynchronous execution and execution with a progress bar.
In addition to being defined in classes, the node class must also be placed in the handlers, using the same name and the same method names and following a specific description format—the parent class and the __init__ method.
For Android, an example:
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,{}
For the server:
class MyClass(Node):
def __init__(self, node_id=None, config_uid=None):
super().__init__(node_id, config_uid)
When defining class methods, you must follow a common format described in the Classes and Global Handlers sections. This concerns method parameters and the structure of the returned tuple. For class methods:
def Input(self, input_data=None):
return True,{}
For global handlers:
def onStartConfiguration(input_data):
return True,{}
Sections section¶
“sections” – an array of sections
“name” – the display name of the section
“code” – the section ID
“commands” – a list of commands as a comma-separated list <command caption>|<command id>. When the button is pressed, a global event onStartMenuCommand is generated, and the command ID is passed as a parameter
Server aliases¶
If the RemoteClass construct is used on the client (essentially a wrapper around the server API), then at least one server with “is_default”: true must be defined. If there are other servers, they are also specified here. In that case, their aliases are used in functions. If there is only one server, the alias can be omitted.
“servers” – an array of server aliases
Server object keys:
“alias” – server alias used in functions for working with remote servers
“url” – server address
“is_default” – flag indicating the default server
“Datasets” section¶
“datasets” – an array of “Dataset” objects
“name” – dataset name, used to access it in the application
- “hash_indexes” – a list of record keys for hash indexes as an array. Example: [
“barcode”, “article”
]
- “text_indexes” – a list of full-text search fields as an array. Example: [
“name”
]
“view_template” – a template for displaying a dataset record in a form input field. Example: “{name}, {article}”
** “api_url” – direct URL for accessing the dataset. This field is mandatory. The generation principle can be seen in the example.
Full configuration example¶
{
"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
}
]
}